wined3d: Release the allocator lock on error in wined3d_allocator_chunk_vk_map().
[wine.git] / dlls / wined3d / context_vk.c
blobfd6d810f0e2814eff798c784a5195dceb1a1720b
1 /*
2 * Copyright 2002-2004 Jason Edmeades
3 * Copyright 2002-2004 Raphael Junqueira
4 * Copyright 2004 Christian Costa
5 * Copyright 2005 Oliver Stieber
6 * Copyright 2006, 2008 Henri Verbeet
7 * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
8 * Copyright 2009-2020 Henri Verbeet for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
27 #include "wined3d_private.h"
29 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
31 VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op)
33 switch (op)
35 case WINED3D_CMP_NEVER:
36 return VK_COMPARE_OP_NEVER;
37 case WINED3D_CMP_LESS:
38 return VK_COMPARE_OP_LESS;
39 case WINED3D_CMP_EQUAL:
40 return VK_COMPARE_OP_EQUAL;
41 case WINED3D_CMP_LESSEQUAL:
42 return VK_COMPARE_OP_LESS_OR_EQUAL;
43 case WINED3D_CMP_GREATER:
44 return VK_COMPARE_OP_GREATER;
45 case WINED3D_CMP_NOTEQUAL:
46 return VK_COMPARE_OP_NOT_EQUAL;
47 case WINED3D_CMP_GREATEREQUAL:
48 return VK_COMPARE_OP_GREATER_OR_EQUAL;
49 case WINED3D_CMP_ALWAYS:
50 return VK_COMPARE_OP_ALWAYS;
51 default:
52 if (!op)
53 WARN("Unhandled compare operation %#x.\n", op);
54 else
55 FIXME("Unhandled compare operation %#x.\n", op);
56 return VK_COMPARE_OP_NEVER;
60 VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type)
62 switch (shader_type)
64 case WINED3D_SHADER_TYPE_VERTEX:
65 return VK_SHADER_STAGE_VERTEX_BIT;
66 case WINED3D_SHADER_TYPE_HULL:
67 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
68 case WINED3D_SHADER_TYPE_DOMAIN:
69 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
70 case WINED3D_SHADER_TYPE_GEOMETRY:
71 return VK_SHADER_STAGE_GEOMETRY_BIT;
72 case WINED3D_SHADER_TYPE_PIXEL:
73 return VK_SHADER_STAGE_FRAGMENT_BIT;
74 case WINED3D_SHADER_TYPE_COMPUTE:
75 return VK_SHADER_STAGE_COMPUTE_BIT;
76 default:
77 ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type));
78 return 0;
82 static VkBlendFactor vk_blend_factor_from_wined3d(enum wined3d_blend blend,
83 const struct wined3d_format *dst_format, bool alpha)
85 switch (blend)
87 case WINED3D_BLEND_ZERO:
88 return VK_BLEND_FACTOR_ZERO;
89 case WINED3D_BLEND_ONE:
90 return VK_BLEND_FACTOR_ONE;
91 case WINED3D_BLEND_SRCCOLOR:
92 return VK_BLEND_FACTOR_SRC_COLOR;
93 case WINED3D_BLEND_INVSRCCOLOR:
94 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
95 case WINED3D_BLEND_SRCALPHA:
96 return VK_BLEND_FACTOR_SRC_ALPHA;
97 case WINED3D_BLEND_INVSRCALPHA:
98 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
99 case WINED3D_BLEND_DESTALPHA:
100 if (dst_format->alpha_size)
101 return VK_BLEND_FACTOR_DST_ALPHA;
102 return VK_BLEND_FACTOR_ONE;
103 case WINED3D_BLEND_INVDESTALPHA:
104 if (dst_format->alpha_size)
105 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
106 return VK_BLEND_FACTOR_ZERO;
107 case WINED3D_BLEND_DESTCOLOR:
108 return VK_BLEND_FACTOR_DST_COLOR;
109 case WINED3D_BLEND_INVDESTCOLOR:
110 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
111 case WINED3D_BLEND_SRCALPHASAT:
112 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
113 case WINED3D_BLEND_BLENDFACTOR:
114 if (alpha)
115 return VK_BLEND_FACTOR_CONSTANT_ALPHA;
116 return VK_BLEND_FACTOR_CONSTANT_COLOR;
117 case WINED3D_BLEND_INVBLENDFACTOR:
118 if (alpha)
119 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
120 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
121 case WINED3D_BLEND_SRC1COLOR:
122 return VK_BLEND_FACTOR_SRC1_COLOR;
123 case WINED3D_BLEND_INVSRC1COLOR:
124 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
125 case WINED3D_BLEND_SRC1ALPHA:
126 return VK_BLEND_FACTOR_SRC1_ALPHA;
127 case WINED3D_BLEND_INVSRC1ALPHA:
128 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
129 default:
130 FIXME("Unhandled blend %#x.\n", blend);
131 return VK_BLEND_FACTOR_ZERO;
135 static VkBlendOp vk_blend_op_from_wined3d(enum wined3d_blend_op op)
137 switch (op)
139 case WINED3D_BLEND_OP_ADD:
140 return VK_BLEND_OP_ADD;
141 case WINED3D_BLEND_OP_SUBTRACT:
142 return VK_BLEND_OP_SUBTRACT;
143 case WINED3D_BLEND_OP_REVSUBTRACT:
144 return VK_BLEND_OP_REVERSE_SUBTRACT;
145 case WINED3D_BLEND_OP_MIN:
146 return VK_BLEND_OP_MIN;
147 case WINED3D_BLEND_OP_MAX:
148 return VK_BLEND_OP_MAX;
149 default:
150 FIXME("Unhandled blend op %#x.\n", op);
151 return VK_BLEND_OP_ADD;
155 static VkColorComponentFlags vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask)
157 VkColorComponentFlags vk_mask = 0;
159 if (wined3d_mask & WINED3DCOLORWRITEENABLE_RED)
160 vk_mask |= VK_COLOR_COMPONENT_R_BIT;
161 if (wined3d_mask & WINED3DCOLORWRITEENABLE_GREEN)
162 vk_mask |= VK_COLOR_COMPONENT_G_BIT;
163 if (wined3d_mask & WINED3DCOLORWRITEENABLE_BLUE)
164 vk_mask |= VK_COLOR_COMPONENT_B_BIT;
165 if (wined3d_mask & WINED3DCOLORWRITEENABLE_ALPHA)
166 vk_mask |= VK_COLOR_COMPONENT_A_BIT;
168 return vk_mask;
171 static VkCullModeFlags vk_cull_mode_from_wined3d(enum wined3d_cull mode)
173 switch (mode)
175 case WINED3D_CULL_NONE:
176 return VK_CULL_MODE_NONE;
177 case WINED3D_CULL_FRONT:
178 return VK_CULL_MODE_FRONT_BIT;
179 case WINED3D_CULL_BACK:
180 return VK_CULL_MODE_BACK_BIT;
181 default:
182 FIXME("Unhandled cull mode %#x.\n", mode);
183 return VK_CULL_MODE_NONE;
187 static VkPrimitiveTopology vk_topology_from_wined3d(enum wined3d_primitive_type t)
189 switch (t)
191 case WINED3D_PT_POINTLIST:
192 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
193 case WINED3D_PT_LINELIST:
194 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
195 case WINED3D_PT_LINESTRIP:
196 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
197 case WINED3D_PT_TRIANGLELIST:
198 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
199 case WINED3D_PT_TRIANGLESTRIP:
200 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
201 case WINED3D_PT_TRIANGLEFAN:
202 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
203 case WINED3D_PT_LINELIST_ADJ:
204 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
205 case WINED3D_PT_LINESTRIP_ADJ:
206 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
207 case WINED3D_PT_TRIANGLELIST_ADJ:
208 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
209 case WINED3D_PT_TRIANGLESTRIP_ADJ:
210 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
211 case WINED3D_PT_PATCH:
212 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
213 default:
214 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t));
215 case WINED3D_PT_UNDEFINED:
216 return ~0u;
220 static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op)
222 switch (op)
224 case WINED3D_STENCIL_OP_KEEP:
225 return VK_STENCIL_OP_KEEP;
226 case WINED3D_STENCIL_OP_ZERO:
227 return VK_STENCIL_OP_ZERO;
228 case WINED3D_STENCIL_OP_REPLACE:
229 return VK_STENCIL_OP_REPLACE;
230 case WINED3D_STENCIL_OP_INCR_SAT:
231 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
232 case WINED3D_STENCIL_OP_DECR_SAT:
233 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
234 case WINED3D_STENCIL_OP_INVERT:
235 return VK_STENCIL_OP_INVERT;
236 case WINED3D_STENCIL_OP_INCR:
237 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
238 case WINED3D_STENCIL_OP_DECR:
239 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
240 default:
241 if (!op)
242 WARN("Unhandled stencil operation %#x.\n", op);
243 else
244 FIXME("Unhandled stencil operation %#x.\n", op);
245 return VK_STENCIL_OP_KEEP;
249 static void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk)
251 wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
254 static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk)
256 wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
259 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
260 struct wined3d_context_vk *context_vk)
262 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
263 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
264 void *map_ptr;
265 VkResult vr;
267 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
268 wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
270 wined3d_allocator_chunk_vk_lock(chunk_vk);
272 if (!chunk_vk->c.map_ptr && (vr = VK_CALL(vkMapMemory(device_vk->vk_device,
273 chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
275 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
276 wined3d_allocator_chunk_vk_unlock(chunk_vk);
277 return NULL;
280 ++chunk_vk->c.map_count;
281 map_ptr = chunk_vk->c.map_ptr;
283 wined3d_allocator_chunk_vk_unlock(chunk_vk);
285 return map_ptr;
288 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
289 struct wined3d_context_vk *context_vk)
291 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
292 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
294 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
296 wined3d_allocator_chunk_vk_lock(chunk_vk);
298 if (--chunk_vk->c.map_count)
300 wined3d_allocator_chunk_vk_unlock(chunk_vk);
301 return;
304 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
305 chunk_vk->c.map_ptr = NULL;
307 wined3d_allocator_chunk_vk_unlock(chunk_vk);
310 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
311 unsigned int pool, size_t size)
313 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
314 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
315 VkMemoryAllocateInfo allocate_info;
316 VkDeviceMemory vk_memory;
317 VkResult vr;
319 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
320 allocate_info.pNext = NULL;
321 allocate_info.allocationSize = size;
322 allocate_info.memoryTypeIndex = pool;
323 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
325 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
326 return VK_NULL_HANDLE;
329 return vk_memory;
332 static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
333 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
335 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
336 struct wined3d_allocator *allocator = &device_vk->allocator;
337 struct wined3d_allocator_block *block;
339 wined3d_device_vk_allocator_lock(device_vk);
341 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
343 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
344 wined3d_device_vk_allocator_unlock(device_vk);
345 return NULL;
348 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
350 wined3d_device_vk_allocator_unlock(device_vk);
351 *vk_memory = VK_NULL_HANDLE;
352 return NULL;
355 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
357 wined3d_device_vk_allocator_unlock(device_vk);
358 return block;
361 static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block)
363 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
365 assert(block->chunk->allocator == &device_vk->allocator);
366 wined3d_device_vk_allocator_lock(device_vk);
367 wined3d_allocator_block_free(block);
368 wined3d_device_vk_allocator_unlock(device_vk);
371 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
372 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
374 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
375 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
376 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
377 struct wined3d_bo_slab_vk_key key;
378 struct wined3d_bo_slab_vk *slab;
379 struct wine_rb_entry *entry;
380 size_t object_size, idx;
381 size_t alignment;
383 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
384 return false;
386 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
387 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
388 && limits->minTexelBufferOffsetAlignment > alignment)
389 alignment = limits->minTexelBufferOffsetAlignment;
390 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
391 alignment = limits->minUniformBufferOffsetAlignment;
392 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
393 alignment = limits->minStorageBufferOffsetAlignment;
395 object_size = (size + (alignment - 1)) & ~(alignment - 1);
396 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
397 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
398 key.memory_type = memory_type;
399 key.usage = usage;
400 key.size = 32 * object_size;
402 wined3d_device_vk_allocator_lock(device_vk);
404 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
406 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
407 TRACE("Using existing bo slab %p.\n", slab);
409 else
411 if (!(slab = heap_alloc_zero(sizeof(*slab))))
413 wined3d_device_vk_allocator_unlock(device_vk);
414 ERR("Failed to allocate bo slab.\n");
415 return false;
418 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
420 wined3d_device_vk_allocator_unlock(device_vk);
421 ERR("Failed to add slab to available tree.\n");
422 heap_free(slab);
423 return false;
426 slab->requested_memory_type = memory_type;
427 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
429 wined3d_device_vk_allocator_unlock(device_vk);
430 ERR("Failed to create slab bo.\n");
431 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
432 heap_free(slab);
433 return false;
435 slab->map = ~0u;
437 TRACE("Created new bo slab %p.\n", slab);
440 idx = wined3d_bit_scan(&slab->map);
441 if (!slab->map)
443 if (slab->next)
445 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
446 slab->next = NULL;
448 else
450 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
454 wined3d_device_vk_allocator_unlock(device_vk);
456 *bo = slab->bo;
457 bo->memory = NULL;
458 bo->slab = slab;
459 bo->b.buffer_offset = idx * object_size;
460 bo->b.memory_offset = slab->bo.b.memory_offset + bo->b.buffer_offset;
461 bo->size = size;
462 list_init(&bo->b.users);
463 bo->command_buffer_id = 0;
464 bo->host_synced = false;
466 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
467 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
468 wine_dbgstr_longlong(bo->b.buffer_offset), bo);
470 return true;
473 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
474 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
476 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
477 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
478 VkMemoryRequirements memory_requirements;
479 struct wined3d_adapter_vk *adapter_vk;
480 VkBufferCreateInfo create_info;
481 unsigned int memory_type_idx;
482 VkResult vr;
484 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
485 return TRUE;
487 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
489 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
490 create_info.pNext = NULL;
491 create_info.flags = 0;
492 create_info.size = size;
493 create_info.usage = usage;
494 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
495 create_info.queueFamilyIndexCount = 0;
496 create_info.pQueueFamilyIndices = NULL;
498 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
500 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
501 return FALSE;
504 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
506 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
507 memory_requirements.memoryTypeBits, memory_type);
508 if (memory_type_idx == ~0u)
510 ERR("Failed to find suitable memory type.\n");
511 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
512 return FALSE;
514 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
515 memory_type_idx, memory_requirements.size, &bo->vk_memory);
516 if (!bo->vk_memory)
518 ERR("Failed to allocate buffer memory.\n");
519 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
520 return FALSE;
522 bo->b.memory_offset = bo->memory ? bo->memory->offset : 0;
524 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
525 bo->vk_memory, bo->b.memory_offset))) < 0)
527 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
528 if (bo->memory)
529 wined3d_context_vk_free_memory(context_vk, bo->memory);
530 else
531 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
532 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
533 return FALSE;
536 bo->b.map_ptr = NULL;
537 bo->b.buffer_offset = 0;
538 bo->size = size;
539 bo->usage = usage;
540 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
541 bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
542 list_init(&bo->b.users);
543 bo->command_buffer_id = 0;
544 bo->slab = NULL;
545 bo->host_synced = false;
547 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
548 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
550 return TRUE;
553 BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkImageType vk_image_type,
554 VkImageUsageFlags usage, VkFormat vk_format, unsigned int width, unsigned int height, unsigned int depth,
555 unsigned int sample_count, unsigned int mip_levels, unsigned int layer_count, unsigned int flags,
556 struct wined3d_image_vk *image)
558 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
559 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
560 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
561 VkMemoryRequirements memory_requirements;
562 VkImageCreateInfo create_info;
563 unsigned int memory_type_idx;
564 VkResult vr;
566 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
567 create_info.pNext = NULL;
568 create_info.flags = flags;
569 create_info.imageType = vk_image_type;
570 create_info.format = vk_format;
571 create_info.extent.width = width;
572 create_info.extent.height = height;
573 create_info.extent.depth = depth;
574 create_info.mipLevels = mip_levels;
575 create_info.arrayLayers = layer_count;
576 create_info.samples = sample_count;
577 create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
578 create_info.usage = usage;
579 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
580 create_info.queueFamilyIndexCount = 0;
581 create_info.pQueueFamilyIndices = NULL;
582 create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
584 image->command_buffer_id = 0;
586 vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &image->vk_image));
587 if (vr != VK_SUCCESS)
589 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr));
590 image->vk_image = VK_NULL_HANDLE;
591 return FALSE;
594 VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image,
595 &memory_requirements));
597 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
598 memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
599 if (memory_type_idx == ~0u)
601 ERR("Failed to find suitable image memory type.\n");
602 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
603 image->vk_image = VK_NULL_HANDLE;
604 return FALSE;
607 image->memory = wined3d_context_vk_allocate_memory(context_vk, memory_type_idx,
608 memory_requirements.size, &image->vk_memory);
609 if (!image->vk_memory)
611 ERR("Failed to allocate image memory.\n");
612 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
613 image->vk_image = VK_NULL_HANDLE;
614 return FALSE;
617 vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, image->vk_memory,
618 image->memory ? image->memory->offset : 0));
619 if (vr != VK_SUCCESS)
621 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
622 if (image->memory)
623 wined3d_context_vk_free_memory(context_vk, image->memory);
624 else
625 VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
626 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
627 image->memory = NULL;
628 image->vk_memory = VK_NULL_HANDLE;
629 image->vk_image = VK_NULL_HANDLE;
630 return FALSE;
633 return TRUE;
636 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
638 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
639 struct wined3d_retired_object_vk *o;
641 if (retired->free)
643 o = retired->free;
644 retired->free = o->u.next;
645 return o;
648 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
649 retired->count + 1, sizeof(*retired->objects)))
650 return NULL;
652 return &retired->objects[retired->count++];
655 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk *context_vk,
656 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
658 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
659 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
660 struct wined3d_retired_object_vk *o;
662 if (context_vk->completed_command_buffer_id > command_buffer_id)
664 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
665 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
666 return;
669 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
671 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
672 return;
675 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
676 o->u.vk_framebuffer = vk_framebuffer;
677 o->command_buffer_id = command_buffer_id;
680 static void wined3d_context_vk_destroy_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
681 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
683 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
684 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
685 struct wined3d_retired_object_vk *o;
687 if (context_vk->completed_command_buffer_id > command_buffer_id)
689 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
690 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
691 return;
694 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
696 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
697 return;
700 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
701 o->u.vk_descriptor_pool = vk_descriptor_pool;
702 o->command_buffer_id = command_buffer_id;
705 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
706 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
708 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
709 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
710 struct wined3d_retired_object_vk *o;
712 if (context_vk->completed_command_buffer_id > command_buffer_id)
714 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
715 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
716 return;
719 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
721 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
722 return;
725 o->type = WINED3D_RETIRED_MEMORY_VK;
726 o->u.vk_memory = vk_memory;
727 o->command_buffer_id = command_buffer_id;
730 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
731 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
733 struct wined3d_retired_object_vk *o;
735 if (context_vk->completed_command_buffer_id > command_buffer_id)
737 wined3d_context_vk_free_memory(context_vk, block);
738 TRACE("Freed block %p.\n", block);
739 return;
742 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
744 ERR("Leaking block %p.\n", block);
745 return;
748 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
749 o->u.block = block;
750 o->command_buffer_id = command_buffer_id;
753 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
754 SIZE_T idx, struct wined3d_context_vk *context_vk)
756 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
757 struct wined3d_bo_slab_vk_key key;
758 struct wine_rb_entry *entry;
760 TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
762 wined3d_device_vk_allocator_lock(device_vk);
764 if (!slab->map)
766 key.memory_type = slab->requested_memory_type;
767 key.usage = slab->bo.usage;
768 key.size = slab->bo.size;
770 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
772 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
773 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
775 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
777 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
780 slab->map |= 1u << idx;
782 wined3d_device_vk_allocator_unlock(device_vk);
785 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
786 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
788 struct wined3d_retired_object_vk *o;
790 if (context_vk->completed_command_buffer_id > command_buffer_id)
792 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
793 return;
796 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
798 ERR("Leaking slab %p, slice %#lx.\n", slab, idx);
799 return;
802 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
803 o->u.slice.slab = slab;
804 o->u.slice.idx = idx;
805 o->command_buffer_id = command_buffer_id;
808 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk *context_vk,
809 VkBuffer vk_buffer, uint64_t command_buffer_id)
811 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
812 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
813 struct wined3d_retired_object_vk *o;
815 if (context_vk->completed_command_buffer_id > command_buffer_id)
817 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
818 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
819 return;
822 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
824 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
825 return;
828 o->type = WINED3D_RETIRED_BUFFER_VK;
829 o->u.vk_buffer = vk_buffer;
830 o->command_buffer_id = command_buffer_id;
833 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk *context_vk,
834 VkImage vk_image, uint64_t command_buffer_id)
836 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
837 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
838 struct wined3d_retired_object_vk *o;
840 if (context_vk->completed_command_buffer_id > command_buffer_id)
842 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
843 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
844 return;
847 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
849 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
850 return;
853 o->type = WINED3D_RETIRED_IMAGE_VK;
854 o->u.vk_image = vk_image;
855 o->command_buffer_id = command_buffer_id;
858 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk *context_vk,
859 VkBufferView vk_view, uint64_t command_buffer_id)
861 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
862 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
863 struct wined3d_retired_object_vk *o;
865 if (context_vk->completed_command_buffer_id > command_buffer_id)
867 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
868 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
869 return;
872 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
874 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
875 return;
878 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
879 o->u.vk_buffer_view = vk_view;
880 o->command_buffer_id = command_buffer_id;
883 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk *context_vk,
884 VkImageView vk_view, uint64_t command_buffer_id)
886 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
887 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
888 struct wined3d_retired_object_vk *o;
890 if (context_vk->completed_command_buffer_id > command_buffer_id)
892 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
893 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
894 return;
897 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
899 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
900 return;
903 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
904 o->u.vk_image_view = vk_view;
905 o->command_buffer_id = command_buffer_id;
908 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
909 VkSampler vk_sampler, uint64_t command_buffer_id)
911 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
912 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
913 struct wined3d_retired_object_vk *o;
915 if (context_vk->completed_command_buffer_id > command_buffer_id)
917 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
918 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
919 return;
922 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
924 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
925 return;
928 o->type = WINED3D_RETIRED_SAMPLER_VK;
929 o->u.vk_sampler = vk_sampler;
930 o->command_buffer_id = command_buffer_id;
933 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
935 wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
936 if (image->memory)
937 wined3d_context_vk_destroy_allocator_block(context_vk, image->memory,
938 image->command_buffer_id);
939 else
940 wined3d_context_vk_destroy_vk_memory(context_vk, image->vk_memory, image->command_buffer_id);
942 image->vk_image = VK_NULL_HANDLE;
943 image->vk_memory = VK_NULL_HANDLE;
944 image->memory = NULL;
947 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
949 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
950 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
951 struct wined3d_bo_slab_vk *slab_vk;
952 size_t object_size, idx;
954 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
956 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
957 context_vk->retired_bo_size += bo->size;
959 if ((slab_vk = bo->slab))
961 if (bo->b.map_ptr)
962 wined3d_bo_slab_vk_unmap(slab_vk, context_vk);
963 object_size = slab_vk->bo.size / 32;
964 idx = bo->b.buffer_offset / object_size;
965 wined3d_context_vk_destroy_bo_slab_slice(context_vk, slab_vk, idx, bo->command_buffer_id);
966 return;
969 wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
970 if (bo->memory)
972 if (bo->b.map_ptr)
973 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
974 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
975 return;
978 if (bo->b.map_ptr)
979 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
980 wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
983 void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk)
985 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
986 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
987 struct wined3d_command_buffer_vk *buffer;
988 SIZE_T i = 0;
990 while (i < context_vk->submitted.buffer_count)
992 buffer = &context_vk->submitted.buffers[i];
993 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
995 ++i;
996 continue;
999 TRACE("Command buffer %p with id 0x%s has finished.\n",
1000 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1001 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
1002 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1003 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1005 if (buffer->id > context_vk->completed_command_buffer_id)
1006 context_vk->completed_command_buffer_id = buffer->id;
1007 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
1011 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk)
1013 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1014 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
1015 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1016 struct wined3d_retired_object_vk *o;
1017 uint64_t command_buffer_id;
1018 SIZE_T i = 0;
1020 wined3d_context_vk_poll_command_buffers(context_vk);
1021 command_buffer_id = context_vk->completed_command_buffer_id;
1023 retired->free = NULL;
1024 for (i = retired->count; i; --i)
1026 o = &retired->objects[i - 1];
1028 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
1029 continue;
1031 switch (o->type)
1033 case WINED3D_RETIRED_FREE_VK:
1034 /* Nothing to do. */
1035 break;
1037 case WINED3D_RETIRED_FRAMEBUFFER_VK:
1038 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
1039 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
1040 break;
1042 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
1043 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, o->u.vk_descriptor_pool, NULL));
1044 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
1045 break;
1047 case WINED3D_RETIRED_MEMORY_VK:
1048 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
1049 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
1050 break;
1052 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
1053 TRACE("Destroying block %p.\n", o->u.block);
1054 wined3d_context_vk_free_memory(context_vk, o->u.block);
1055 break;
1057 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
1058 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
1059 break;
1061 case WINED3D_RETIRED_BUFFER_VK:
1062 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
1063 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
1064 break;
1066 case WINED3D_RETIRED_IMAGE_VK:
1067 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
1068 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
1069 break;
1071 case WINED3D_RETIRED_BUFFER_VIEW_VK:
1072 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
1073 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
1074 break;
1076 case WINED3D_RETIRED_IMAGE_VIEW_VK:
1077 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
1078 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
1079 break;
1081 case WINED3D_RETIRED_SAMPLER_VK:
1082 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
1083 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
1084 break;
1086 default:
1087 ERR("Unhandled object type %#x.\n", o->type);
1088 break;
1091 if (i == retired->count)
1093 --retired->count;
1094 continue;
1097 o->type = WINED3D_RETIRED_FREE_VK;
1098 o->u.next = retired->free;
1099 retired->free = o;
1103 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
1105 struct wined3d_context_vk *context_vk = ctx;
1106 struct wined3d_bo_slab_vk *slab, *next;
1108 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
1109 while (slab)
1111 next = slab->next;
1112 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
1113 heap_free(slab);
1114 slab = next;
1118 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
1120 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
1121 struct wined3d_graphics_pipeline_vk, entry);
1122 struct wined3d_context_vk *context_vk = ctx;
1123 const struct wined3d_vk_info *vk_info;
1124 struct wined3d_device_vk *device_vk;
1126 vk_info = context_vk->vk_info;
1127 device_vk = wined3d_device_vk(context_vk->c.device);
1129 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
1130 heap_free(pipeline_vk);
1133 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
1135 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
1136 struct wined3d_pipeline_layout_vk, entry);
1137 struct wined3d_context_vk *context_vk = ctx;
1138 const struct wined3d_vk_info *vk_info;
1139 struct wined3d_device_vk *device_vk;
1141 vk_info = context_vk->vk_info;
1142 device_vk = wined3d_device_vk(context_vk->c.device);
1144 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
1145 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
1146 heap_free(layout->key.bindings);
1147 heap_free(layout);
1150 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
1151 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1153 struct wined3d_render_pass_attachment_vk *a;
1154 struct wined3d_rendertarget_view *view;
1155 unsigned int i;
1157 memset(key, 0, sizeof(*key));
1159 for (i = 0; i < rt_count; ++i)
1161 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1162 continue;
1164 a = &key->rt[i];
1165 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1166 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1167 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1168 key->rt_mask |= 1u << i;
1171 if (depth_stencil && (view = fb->depth_stencil))
1173 a = &key->ds;
1174 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1175 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1176 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1177 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1180 key->clear_flags = clear_flags;
1183 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1184 struct wined3d_context_vk *context_vk)
1186 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1187 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1189 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1192 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1193 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1195 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1196 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1197 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1198 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1199 const struct wined3d_render_pass_attachment_vk *a;
1200 VkAttachmentReference ds_attachment_reference;
1201 VkAttachmentReference *ds_reference = NULL;
1202 unsigned int attachment_count, rt_count, i;
1203 VkAttachmentDescription *attachment;
1204 VkSubpassDescription sub_pass_desc;
1205 VkRenderPassCreateInfo pass_desc;
1206 uint32_t mask;
1207 VkResult vr;
1209 rt_count = 0;
1210 attachment_count = 0;
1211 mask = key->rt_mask & wined3d_mask_from_size(WINED3D_MAX_RENDER_TARGETS);
1212 while (mask)
1214 i = wined3d_bit_scan(&mask);
1215 a = &key->rt[i];
1217 attachment = &attachments[attachment_count];
1218 attachment->flags = 0;
1219 attachment->format = a->vk_format;
1220 attachment->samples = a->vk_samples;
1221 if (key->clear_flags & WINED3DCLEAR_TARGET)
1222 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1223 else
1224 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1225 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1226 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1227 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1228 attachment->initialLayout = a->vk_layout;
1229 attachment->finalLayout = a->vk_layout;
1231 attachment_references[i].attachment = attachment_count;
1232 attachment_references[i].layout = a->vk_layout;
1234 ++attachment_count;
1235 rt_count = i + 1;
1238 mask = ~key->rt_mask & wined3d_mask_from_size(rt_count);
1239 while (mask)
1241 i = wined3d_bit_scan(&mask);
1242 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1243 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1246 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1248 a = &key->ds;
1250 attachment = &attachments[attachment_count];
1251 attachment->flags = 0;
1252 attachment->format = a->vk_format;
1253 attachment->samples = a->vk_samples;
1254 if (key->clear_flags & WINED3DCLEAR_ZBUFFER)
1255 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1256 else
1257 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1258 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1259 if (key->clear_flags & WINED3DCLEAR_STENCIL)
1260 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1261 else
1262 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1263 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1264 attachment->initialLayout = a->vk_layout;
1265 attachment->finalLayout = a->vk_layout;
1267 ds_reference = &ds_attachment_reference;
1268 ds_reference->attachment = attachment_count;
1269 ds_reference->layout = a->vk_layout;
1271 ++attachment_count;
1274 sub_pass_desc.flags = 0;
1275 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1276 sub_pass_desc.inputAttachmentCount = 0;
1277 sub_pass_desc.pInputAttachments = NULL;
1278 sub_pass_desc.colorAttachmentCount = rt_count;
1279 sub_pass_desc.pColorAttachments = attachment_references;
1280 sub_pass_desc.pResolveAttachments = NULL;
1281 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1282 sub_pass_desc.preserveAttachmentCount = 0;
1283 sub_pass_desc.pPreserveAttachments = NULL;
1285 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1286 pass_desc.pNext = NULL;
1287 pass_desc.flags = 0;
1288 pass_desc.attachmentCount = attachment_count;
1289 pass_desc.pAttachments = attachments;
1290 pass_desc.subpassCount = 1;
1291 pass_desc.pSubpasses = &sub_pass_desc;
1292 pass_desc.dependencyCount = 0;
1293 pass_desc.pDependencies = NULL;
1295 pass->key = *key;
1296 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1297 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1299 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1300 return false;
1303 return true;
1306 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1307 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1309 struct wined3d_render_pass_key_vk key;
1310 struct wined3d_render_pass_vk *pass;
1311 struct wine_rb_entry *entry;
1313 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1314 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1315 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1317 if (!(pass = heap_alloc(sizeof(*pass))))
1318 return VK_NULL_HANDLE;
1320 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1322 heap_free(pass);
1323 return VK_NULL_HANDLE;
1326 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1328 ERR("Failed to insert render pass.\n");
1329 wined3d_render_pass_vk_cleanup(pass, context_vk);
1330 heap_free(pass);
1331 return VK_NULL_HANDLE;
1334 return pass->vk_render_pass;
1337 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1339 VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1340 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1341 struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
1342 struct wined3d_query_vk *query_vk;
1344 if (context_vk->vk_render_pass)
1346 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1347 wined3d_query_vk_suspend(query_vk, context_vk);
1349 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1350 context_vk->vk_render_pass = VK_NULL_HANDLE;
1351 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1352 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1354 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1356 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1358 ERR("Failed to allocate new query.\n");
1359 break;
1364 if (context_vk->vk_framebuffer)
1366 wined3d_context_vk_destroy_vk_framebuffer(context_vk,
1367 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1368 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1371 if (vk_command_buffer)
1373 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
1374 struct wined3d_query_pool_vk, completed_entry)
1376 list_remove(&pool_vk->completed_entry);
1377 list_init(&pool_vk->completed_entry);
1378 wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
1383 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1385 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1386 struct wined3d_render_pass_vk, entry);
1388 wined3d_render_pass_vk_cleanup(pass, ctx);
1389 heap_free(pass);
1392 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1394 heap_free(writes->writes);
1397 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1399 struct wined3d_query_pool_vk *pool_vk, *entry;
1401 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1403 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1404 heap_free(pool_vk);
1408 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1409 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1411 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1412 struct wined3d_query_pool_vk *pool_vk, *entry;
1413 struct list *free_pools;
1414 size_t idx;
1416 switch (type)
1418 case WINED3D_QUERY_TYPE_OCCLUSION:
1419 free_pools = &context_vk->free_occlusion_query_pools;
1420 break;
1422 case WINED3D_QUERY_TYPE_TIMESTAMP:
1423 free_pools = &context_vk->free_timestamp_query_pools;
1424 break;
1426 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1427 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1428 break;
1430 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1431 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1432 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1433 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1434 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1435 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1436 break;
1438 default:
1439 FIXME("Unhandled query type %#x.\n", type);
1440 return false;
1443 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1445 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1446 goto done;
1447 list_remove(&pool_vk->entry);
1450 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1451 return false;
1452 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1454 heap_free(pool_vk);
1455 return false;
1458 if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET])
1460 VK_CALL(vkResetQueryPoolEXT(wined3d_device_vk(context_vk->c.device)->vk_device,
1461 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1463 else
1465 wined3d_context_vk_end_current_render_pass(context_vk);
1466 VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
1467 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1470 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1472 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1473 heap_free(pool_vk);
1474 return false;
1477 done:
1478 pool_idx->pool_vk = pool_vk;
1479 pool_idx->idx = idx;
1481 return true;
1484 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1486 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1487 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1488 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1490 if (buffer->vk_command_buffer)
1492 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1493 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1494 buffer->vk_command_buffer = VK_NULL_HANDLE;
1497 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1498 context_vk->completed_command_buffer_id = buffer->id;
1500 heap_free(context_vk->compute.bindings.bindings);
1501 heap_free(context_vk->graphics.bindings.bindings);
1502 if (context_vk->vk_descriptor_pool)
1503 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pool, NULL));
1504 if (context_vk->vk_framebuffer)
1505 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1506 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1507 if (context_vk->vk_so_counter_bo.vk_buffer)
1508 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1509 wined3d_context_vk_cleanup_resources(context_vk);
1510 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1511 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1512 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1513 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1514 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1515 heap_free(context_vk->pending_queries.queries);
1516 heap_free(context_vk->submitted.buffers);
1517 heap_free(context_vk->retired.objects);
1519 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1520 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1521 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1522 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1524 wined3d_context_cleanup(&context_vk->c);
1527 void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *context_vk,
1528 struct wined3d_query_vk *query_vk)
1530 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1531 struct wined3d_pending_query_vk *p;
1532 size_t i;
1534 pending->free_idx = ~(size_t)0;
1535 for (i = pending->count; i; --i)
1537 p = &pending->queries[i - 1];
1539 if (p->query_vk)
1541 if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx))
1542 continue;
1543 --p->query_vk->pending_count;
1546 if (i == pending->count)
1548 --pending->count;
1549 continue;
1552 p->query_vk = NULL;
1553 p->pool_idx.pool_vk = NULL;
1554 p->pool_idx.idx = pending->free_idx;
1555 pending->free_idx = i - 1;
1559 void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk *context_vk)
1561 wined3d_context_vk_remove_pending_queries(context_vk, NULL);
1564 void wined3d_context_vk_add_pending_query(struct wined3d_context_vk *context_vk, struct wined3d_query_vk *query_vk)
1566 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1567 struct wined3d_pending_query_vk *p;
1569 if (pending->free_idx != ~(size_t)0)
1571 p = &pending->queries[pending->free_idx];
1572 pending->free_idx = p->pool_idx.idx;
1574 else
1576 if (!wined3d_array_reserve((void **)&pending->queries, &pending->size,
1577 pending->count + 1, sizeof(*pending->queries)))
1579 ERR("Failed to allocate entry.\n");
1580 return;
1582 p = &pending->queries[pending->count++];
1585 p->query_vk = query_vk;
1586 p->pool_idx = query_vk->pool_idx;
1587 ++query_vk->pending_count;
1590 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1592 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1593 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1594 VkCommandBufferAllocateInfo command_buffer_info;
1595 struct wined3d_command_buffer_vk *buffer;
1596 VkCommandBufferBeginInfo begin_info;
1597 struct wined3d_query_vk *query_vk;
1598 VkResult vr;
1600 TRACE("context_vk %p.\n", context_vk);
1602 buffer = &context_vk->current_command_buffer;
1603 if (buffer->vk_command_buffer)
1605 if (context_vk->retired_bo_size > WINED3D_RETIRED_BO_SIZE_THRESHOLD)
1606 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1607 else
1609 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1610 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1611 return buffer->vk_command_buffer;
1615 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1616 command_buffer_info.pNext = NULL;
1617 command_buffer_info.commandPool = context_vk->vk_command_pool;
1618 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1619 command_buffer_info.commandBufferCount = 1;
1620 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1621 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1623 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1624 return VK_NULL_HANDLE;
1627 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1628 begin_info.pNext = NULL;
1629 begin_info.flags = 0;
1630 begin_info.pInheritanceInfo = NULL;
1631 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1633 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1634 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1635 1, &buffer->vk_command_buffer));
1636 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1639 wined3d_context_vk_accumulate_pending_queries(context_vk);
1640 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1642 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1644 ERR("Failed to allocate new query.\n");
1645 break;
1648 wined3d_query_vk_resume(query_vk, context_vk);
1651 TRACE("Created new command buffer %p with id 0x%s.\n",
1652 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1654 return buffer->vk_command_buffer;
1657 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1658 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1659 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1661 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1662 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1663 struct wined3d_command_buffer_vk *buffer;
1664 struct wined3d_query_vk *query_vk;
1665 VkFenceCreateInfo fence_desc;
1666 VkSubmitInfo submit_info;
1667 VkResult vr;
1669 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1670 "signal_semaphore_count %u, signal_semaphores %p.\n",
1671 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1672 signal_semaphore_count, signal_semaphores);
1674 buffer = &context_vk->current_command_buffer;
1675 if (!buffer->vk_command_buffer)
1676 return;
1678 TRACE("Submitting command buffer %p with id 0x%s.\n",
1679 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1681 wined3d_context_vk_end_current_render_pass(context_vk);
1683 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1684 wined3d_query_vk_suspend(query_vk, context_vk);
1686 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1687 context_vk->update_compute_pipeline = 1;
1688 context_vk->update_stream_output = 1;
1689 context_vk->c.update_shader_resource_bindings = 1;
1690 context_vk->c.update_compute_shader_resource_bindings = 1;
1691 context_vk->c.update_unordered_access_view_bindings = 1;
1692 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1693 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1694 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1695 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1696 context_invalidate_state(&context_vk->c, STATE_STENCIL_REF);
1698 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1700 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1701 fence_desc.pNext = NULL;
1702 fence_desc.flags = 0;
1703 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1704 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1706 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1707 submit_info.pNext = NULL;
1708 submit_info.waitSemaphoreCount = wait_semaphore_count;
1709 submit_info.pWaitSemaphores = wait_semaphores;
1710 submit_info.pWaitDstStageMask = wait_stages;
1711 submit_info.commandBufferCount = 1;
1712 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1713 submit_info.signalSemaphoreCount = signal_semaphore_count;
1714 submit_info.pSignalSemaphores = signal_semaphores;
1716 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1717 ERR("Failed to submit command buffer %p, vr %s.\n",
1718 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1720 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1721 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1722 ERR("Failed to grow submitted command buffer array.\n");
1724 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1726 buffer->vk_command_buffer = VK_NULL_HANDLE;
1727 /* We don't expect this to ever happen, but handle it anyway. */
1728 if (!++buffer->id)
1730 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1731 context_vk->completed_command_buffer_id = 0;
1732 buffer->id = 1;
1734 context_vk->retired_bo_size = 0;
1735 wined3d_context_vk_cleanup_resources(context_vk);
1738 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1740 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1741 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1742 SIZE_T i;
1744 if (id <= context_vk->completed_command_buffer_id
1745 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1746 return;
1748 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1750 if (context_vk->submitted.buffers[i].id != id)
1751 continue;
1753 VK_CALL(vkWaitForFences(device_vk->vk_device, 1,
1754 &context_vk->submitted.buffers[i].vk_fence, VK_TRUE, UINT64_MAX));
1755 wined3d_context_vk_cleanup_resources(context_vk);
1756 return;
1759 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1762 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1763 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1764 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1765 VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range)
1767 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1768 VkImageMemoryBarrier barrier;
1770 wined3d_context_vk_end_current_render_pass(context_vk);
1772 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1773 barrier.pNext = NULL;
1774 barrier.srcAccessMask = src_access_mask;
1775 barrier.dstAccessMask = dst_access_mask;
1776 barrier.oldLayout = old_layout;
1777 barrier.newLayout = new_layout;
1778 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1779 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1780 barrier.image = image;
1781 barrier.subresourceRange = *range;
1783 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1786 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1788 const struct wined3d_render_pass_key_vk *k = key;
1789 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1790 const struct wined3d_render_pass_vk, entry);
1792 return memcmp(k, &pass->key, sizeof(*k));
1795 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1797 const struct wined3d_pipeline_layout_key_vk *a = key;
1798 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1799 const struct wined3d_pipeline_layout_vk, entry)->key;
1801 if (a->binding_count != b->binding_count)
1802 return a->binding_count - b->binding_count;
1803 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1806 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1808 const struct wined3d_graphics_pipeline_key_vk *a = key;
1809 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1810 const struct wined3d_graphics_pipeline_vk, entry)->key;
1811 unsigned int i;
1812 int ret;
1814 if (a->pipeline_desc.stageCount != b->pipeline_desc.stageCount)
1815 return a->pipeline_desc.stageCount - b->pipeline_desc.stageCount;
1816 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1818 if (a->stages[i].module != b->stages[i].module)
1819 return a->stages[i].module - b->stages[i].module;
1822 if (a->divisor_desc.vertexBindingDivisorCount != b->divisor_desc.vertexBindingDivisorCount)
1823 return a->divisor_desc.vertexBindingDivisorCount - b->divisor_desc.vertexBindingDivisorCount;
1824 if ((ret = memcmp(a->divisors, b->divisors,
1825 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1826 return ret;
1828 if (a->input_desc.vertexAttributeDescriptionCount != b->input_desc.vertexAttributeDescriptionCount)
1829 return a->input_desc.vertexAttributeDescriptionCount - b->input_desc.vertexAttributeDescriptionCount;
1830 if ((ret = memcmp(a->attributes, b->attributes,
1831 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1832 return ret;
1833 if (a->input_desc.vertexBindingDescriptionCount != b->input_desc.vertexBindingDescriptionCount)
1834 return a->input_desc.vertexBindingDescriptionCount - b->input_desc.vertexBindingDescriptionCount;
1835 if ((ret = memcmp(a->bindings, b->bindings,
1836 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1837 return ret;
1839 if (a->ia_desc.topology != b->ia_desc.topology)
1840 return a->ia_desc.topology - b->ia_desc.topology;
1841 if (a->ia_desc.primitiveRestartEnable != b->ia_desc.primitiveRestartEnable)
1842 return a->ia_desc.primitiveRestartEnable - b->ia_desc.primitiveRestartEnable;
1844 if (a->ts_desc.patchControlPoints != b->ts_desc.patchControlPoints)
1845 return a->ts_desc.patchControlPoints - b->ts_desc.patchControlPoints;
1847 if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport))))
1848 return ret;
1850 if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor))))
1851 return ret;
1853 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
1854 return ret;
1856 if (a->ms_desc.rasterizationSamples != b->ms_desc.rasterizationSamples)
1857 return a->ms_desc.rasterizationSamples - b->ms_desc.rasterizationSamples;
1858 if (a->ms_desc.alphaToCoverageEnable != b->ms_desc.alphaToCoverageEnable)
1859 return a->ms_desc.alphaToCoverageEnable - b->ms_desc.alphaToCoverageEnable;
1860 if (a->sample_mask != b->sample_mask)
1861 return a->sample_mask - b->sample_mask;
1863 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
1864 return ret;
1866 if (a->blend_desc.attachmentCount != b->blend_desc.attachmentCount)
1867 return a->blend_desc.attachmentCount - b->blend_desc.attachmentCount;
1868 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
1869 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
1870 return ret;
1872 if (a->pipeline_desc.layout != b->pipeline_desc.layout)
1873 return a->pipeline_desc.layout - b->pipeline_desc.layout;
1875 if (a->pipeline_desc.renderPass != b->pipeline_desc.renderPass)
1876 return a->pipeline_desc.renderPass - b->pipeline_desc.renderPass;
1878 return 0;
1881 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
1883 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
1884 const struct wined3d_bo_slab_vk_key *k = key;
1886 if (k->memory_type != slab->requested_memory_type)
1887 return k->memory_type - slab->requested_memory_type;
1888 if (k->usage != slab->bo.usage)
1889 return k->usage - slab->bo.usage;
1890 return k->size - slab->bo.size;
1893 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
1895 struct wined3d_graphics_pipeline_key_vk *key;
1896 VkPipelineShaderStageCreateInfo *stage;
1897 unsigned int i;
1899 static const VkDynamicState dynamic_states[] =
1901 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1902 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
1905 key = &context_vk->graphics.pipeline_key_vk;
1906 memset(key, 0, sizeof(*key));
1908 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
1910 stage = &key->stages[i];
1911 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1912 stage->pName = "main";
1915 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1916 key->input_desc.pVertexBindingDescriptions = key->bindings;
1917 key->input_desc.pVertexAttributeDescriptions = key->attributes;
1919 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1920 key->divisor_desc.pVertexBindingDivisors = key->divisors;
1922 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1924 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1926 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1927 key->vp_desc.viewportCount = 1;
1928 key->vp_desc.pViewports = &key->viewport;
1929 key->vp_desc.scissorCount = 1;
1930 key->vp_desc.pScissors = &key->scissor;
1932 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1933 key->rs_desc.lineWidth = 1.0f;
1935 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1936 key->ms_desc.pSampleMask = &key->sample_mask;
1938 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1939 key->ds_desc.maxDepthBounds = 1.0f;
1941 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1942 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
1943 key->blend_desc.pAttachments = key->blend_attachments;
1944 key->blend_desc.blendConstants[0] = 1.0f;
1945 key->blend_desc.blendConstants[1] = 1.0f;
1946 key->blend_desc.blendConstants[2] = 1.0f;
1947 key->blend_desc.blendConstants[3] = 1.0f;
1949 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1950 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
1951 key->dynamic_desc.pDynamicStates = dynamic_states;
1953 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1954 key->pipeline_desc.pStages = key->stages;
1955 key->pipeline_desc.pVertexInputState = &key->input_desc;
1956 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
1957 key->pipeline_desc.pTessellationState = &key->ts_desc;
1958 key->pipeline_desc.pViewportState = &key->vp_desc;
1959 key->pipeline_desc.pRasterizationState = &key->rs_desc;
1960 key->pipeline_desc.pMultisampleState = &key->ms_desc;
1961 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
1962 key->pipeline_desc.pColorBlendState = &key->blend_desc;
1963 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
1964 key->pipeline_desc.basePipelineIndex = -1;
1967 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
1968 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1970 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
1971 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
1972 const struct wined3d_rasterizer_state_desc *r;
1973 float scale_bias;
1974 union
1976 uint32_t u32;
1977 float f32;
1978 } const_bias;
1980 if (!state->rasterizer_state)
1982 desc->depthClampEnable = VK_FALSE;
1983 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1984 desc->cullMode = VK_CULL_MODE_BACK_BIT;
1985 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
1986 desc->depthBiasEnable = VK_FALSE;
1987 desc->depthBiasConstantFactor = 0.0f;
1988 desc->depthBiasClamp = 0.0f;
1989 desc->depthBiasSlopeFactor = 0.0f;
1991 return;
1994 r = &state->rasterizer_state->desc;
1995 desc->depthClampEnable = !r->depth_clip;
1996 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1997 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
1998 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
2000 scale_bias = r->scale_bias;
2001 const_bias.f32 = r->depth_bias;
2002 if (!scale_bias && !const_bias.f32)
2004 desc->depthBiasEnable = VK_FALSE;
2005 desc->depthBiasConstantFactor = 0.0f;
2006 desc->depthBiasClamp = 0.0f;
2007 desc->depthBiasSlopeFactor = 0.0f;
2009 return;
2012 desc->depthBiasEnable = VK_TRUE;
2013 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
2015 const struct wined3d_rendertarget_view *dsv;
2017 if ((dsv = state->fb.depth_stencil))
2019 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
2020 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
2022 else
2024 desc->depthBiasConstantFactor = 0.0f;
2025 desc->depthBiasSlopeFactor = 0.0f;
2028 else
2030 desc->depthBiasConstantFactor = const_bias.f32;
2031 desc->depthBiasSlopeFactor = scale_bias;
2033 desc->depthBiasClamp = r->depth_bias_clamp;
2036 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
2037 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2039 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
2040 const struct wined3d_blend_state_desc *b;
2041 unsigned int i;
2043 desc->attachmentCount = context_vk->rt_count;
2045 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
2046 if (!state->blend_state)
2048 for (i = 0; i < context_vk->rt_count; ++i)
2050 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
2051 | VK_COLOR_COMPONENT_G_BIT
2052 | VK_COLOR_COMPONENT_B_BIT
2053 | VK_COLOR_COMPONENT_A_BIT;
2056 return;
2059 b = &state->blend_state->desc;
2060 for (i = 0; i < context_vk->rt_count; ++i)
2062 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2063 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2064 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2065 enum wined3d_blend src_blend, dst_blend;
2066 const struct wined3d_format *rt_format;
2068 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2069 if (!rt->enable)
2070 continue;
2072 if (rtv)
2073 rt_format = rtv->format;
2074 else
2075 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2076 a->blendEnable = VK_TRUE;
2078 src_blend = rt->src;
2079 dst_blend = rt->dst;
2080 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2082 src_blend = WINED3D_BLEND_SRCALPHA;
2083 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2085 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2087 src_blend = WINED3D_BLEND_INVSRCALPHA;
2088 dst_blend = WINED3D_BLEND_SRCALPHA;
2090 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2091 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2092 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2094 src_blend = rt->src_alpha;
2095 dst_blend = rt->dst_alpha;
2096 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2097 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2098 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2102 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2104 switch (component_type)
2106 case WINED3D_TYPE_UINT:
2107 return VK_FORMAT_R32G32B32A32_UINT;
2108 case WINED3D_TYPE_INT:
2109 return VK_FORMAT_R32G32B32A32_SINT;
2110 case WINED3D_TYPE_UNKNOWN:
2111 case WINED3D_TYPE_FLOAT:
2112 return VK_FORMAT_R32G32B32A32_SFLOAT;
2114 return VK_FORMAT_UNDEFINED;
2117 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2118 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2120 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2121 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2122 struct wined3d_graphics_pipeline_key_vk *key;
2123 VkPipelineShaderStageCreateInfo *stage;
2124 struct wined3d_stream_info stream_info;
2125 struct wined3d_shader *vertex_shader;
2126 VkPrimitiveTopology vk_topology;
2127 VkShaderModule module;
2128 bool update = false;
2129 uint32_t mask;
2131 *null_buffer_binding = ~0u;
2132 key = &context_vk->graphics.pipeline_key_vk;
2134 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2136 stage_count = 0;
2137 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2139 if (!(module = context_vk->graphics.vk_modules[i]))
2140 continue;
2142 stage = &key->stages[stage_count++];
2143 stage->stage = vk_shader_stage_from_wined3d(i);
2144 stage->module = module;
2147 key->pipeline_desc.stageCount = stage_count;
2149 update = true;
2152 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2153 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2154 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2156 VkVertexInputAttributeDescription *a;
2157 VkVertexInputBindingDescription *b;
2159 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2160 divisor_count = 0;
2161 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2163 VkVertexInputBindingDivisorDescriptionEXT *d;
2164 struct wined3d_stream_info_element *e;
2165 uint32_t binding;
2167 if (!(stream_info.use_map & (1u << i)))
2168 continue;
2170 a = &key->attributes[attribute_count++];
2171 e = &stream_info.elements[i];
2172 binding = e->stream_idx;
2174 a->location = i;
2175 a->binding = binding;
2176 a->format = wined3d_format_vk(e->format)->vk_format;
2177 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2179 if (mask & (1u << binding))
2180 continue;
2181 mask |= 1u << binding;
2183 b = &key->bindings[binding_count++];
2184 b->binding = binding;
2185 b->stride = e->stride;
2186 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2188 if (e->instanced)
2190 d = &key->divisors[divisor_count++];
2191 d->binding = binding;
2192 d->divisor = e->divisor;
2196 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2197 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2199 struct wined3d_shader_signature_element *element;
2200 struct wined3d_shader_signature *signature;
2201 uint32_t null_binding, location;
2203 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2205 if (!state->streams[i].buffer)
2207 null_binding = i;
2208 break;
2212 if (i == ARRAY_SIZE(state->streams))
2214 ERR("No streams left for a null buffer binding.\n");
2216 else
2218 signature = &vertex_shader->input_signature;
2219 for (i = 0; i < signature->element_count; ++i)
2221 element = &signature->elements[i];
2222 location = element->register_idx;
2224 if (!(mask & (1u << location)) || element->sysval_semantic)
2225 continue;
2226 mask &= ~(1u << location);
2228 a = &key->attributes[attribute_count++];
2229 a->location = location;
2230 a->binding = null_binding;
2231 a->format = vk_format_from_component_type(element->component_type);
2232 a->offset = 0;
2235 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2237 b = &key->bindings[binding_count++];
2238 *null_buffer_binding = b->binding = null_binding;
2239 b->stride = 0;
2240 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2245 key->input_desc.pNext = NULL;
2246 key->input_desc.vertexBindingDescriptionCount = binding_count;
2247 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2249 if (divisor_count)
2251 key->input_desc.pNext = &key->divisor_desc;
2252 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2255 update = true;
2258 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2259 if (key->ia_desc.topology != vk_topology)
2261 key->ia_desc.topology = vk_topology;
2262 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2263 && !wined3d_primitive_type_is_list(state->primitive_type);
2265 update = true;
2268 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2270 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2272 update = true;
2275 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2276 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2277 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2279 key->viewport.x = state->viewports[0].x;
2280 key->viewport.y = state->viewports[0].y;
2281 key->viewport.width = state->viewports[0].width;
2282 key->viewport.height = state->viewports[0].height;
2283 key->viewport.minDepth = state->viewports[0].min_z;
2284 key->viewport.maxDepth = state->viewports[0].max_z;
2286 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2288 const RECT *r = &state->scissor_rects[0];
2290 key->scissor.offset.x = r->left;
2291 key->scissor.offset.y = r->top;
2292 key->scissor.extent.width = r->right - r->left;
2293 key->scissor.extent.height = r->bottom - r->top;
2295 else
2297 key->scissor.offset.x = key->viewport.x;
2298 key->scissor.offset.y = key->viewport.y;
2299 key->scissor.extent.width = key->viewport.width;
2300 key->scissor.extent.height = key->viewport.height;
2302 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2303 if (key->scissor.offset.x < 0)
2304 key->scissor.offset.x = 0;
2305 if (key->scissor.offset.y < 0)
2306 key->scissor.offset.y = 0;
2307 key->viewport.y += key->viewport.height;
2308 key->viewport.height = -key->viewport.height;
2310 update = true;
2313 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2314 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2316 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2318 update = true;
2321 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2322 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2324 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2325 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2326 key->sample_mask = state->sample_mask;
2328 update = true;
2331 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2332 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2334 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2336 if (d)
2338 key->ds_desc.depthTestEnable = d->desc.depth;
2339 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2340 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2341 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2342 if (key->ds_desc.stencilTestEnable)
2344 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2345 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2346 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2347 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2348 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2349 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2351 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2352 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2353 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2354 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2355 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2356 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2358 else
2360 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2361 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2364 else
2366 key->ds_desc.depthTestEnable = VK_TRUE;
2367 key->ds_desc.depthWriteEnable = VK_TRUE;
2368 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2369 key->ds_desc.stencilTestEnable = VK_FALSE;
2372 update = true;
2375 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2376 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2378 wined3d_context_vk_update_blend_state(context_vk, state, key);
2380 update = true;
2383 if (key->pipeline_desc.layout != vk_pipeline_layout)
2385 key->pipeline_desc.layout = vk_pipeline_layout;
2387 update = true;
2390 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2392 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2394 update = true;
2397 return update;
2400 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2401 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2403 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2404 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2405 unsigned int fb_width, fb_height, fb_layer_count;
2406 struct wined3d_rendertarget_view_vk *rtv_vk;
2407 struct wined3d_rendertarget_view *view;
2408 const VkPhysicalDeviceLimits *limits;
2409 struct wined3d_query_vk *query_vk;
2410 VkRenderPassBeginInfo begin_info;
2411 unsigned int attachment_count, i;
2412 VkFramebufferCreateInfo fb_desc;
2413 VkResult vr;
2415 if (context_vk->vk_render_pass)
2416 return true;
2418 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2419 fb_width = limits->maxFramebufferWidth;
2420 fb_height = limits->maxFramebufferHeight;
2421 fb_layer_count = limits->maxFramebufferLayers;
2422 attachment_count = 0;
2424 context_vk->rt_count = 0;
2425 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2427 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2428 continue;
2430 rtv_vk = wined3d_rendertarget_view_vk(view);
2431 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2432 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2433 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2435 if (view->width < fb_width)
2436 fb_width = view->width;
2437 if (view->height < fb_height)
2438 fb_height = view->height;
2439 if (view->layer_count < fb_layer_count)
2440 fb_layer_count = view->layer_count;
2441 context_vk->rt_count = i + 1;
2442 ++attachment_count;
2445 if ((view = state->fb.depth_stencil))
2447 rtv_vk = wined3d_rendertarget_view_vk(view);
2448 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2449 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2450 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2452 if (view->width < fb_width)
2453 fb_width = view->width;
2454 if (view->height < fb_height)
2455 fb_height = view->height;
2456 if (view->layer_count < fb_layer_count)
2457 fb_layer_count = view->layer_count;
2458 ++attachment_count;
2461 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2462 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2464 ERR("Failed to get render pass.\n");
2465 return false;
2468 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2469 fb_desc.pNext = NULL;
2470 fb_desc.flags = 0;
2471 fb_desc.renderPass = context_vk->vk_render_pass;
2472 fb_desc.attachmentCount = attachment_count;
2473 fb_desc.pAttachments = vk_views;
2474 fb_desc.width = fb_width;
2475 fb_desc.height = fb_height;
2476 fb_desc.layers = fb_layer_count;
2478 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2480 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2481 return false;
2484 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2485 begin_info.pNext = NULL;
2486 begin_info.renderPass = context_vk->vk_render_pass;
2487 begin_info.framebuffer = context_vk->vk_framebuffer;
2488 begin_info.renderArea.offset.x = 0;
2489 begin_info.renderArea.offset.y = 0;
2490 begin_info.renderArea.extent.width = fb_width;
2491 begin_info.renderArea.extent.height = fb_height;
2492 begin_info.clearValueCount = 0;
2493 begin_info.pClearValues = NULL;
2494 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2496 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2497 wined3d_query_vk_resume(query_vk, context_vk);
2498 return true;
2501 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2502 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2504 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2505 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2506 const struct wined3d_stream_state *stream;
2507 const VkDescriptorBufferInfo *buffer_info;
2508 struct wined3d_buffer_vk *buffer_vk;
2509 struct wined3d_buffer *buffer;
2510 unsigned int i, first, count;
2512 first = 0;
2513 count = 0;
2514 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2516 stream = &state->streams[i];
2518 if ((buffer = stream->buffer))
2520 buffer_vk = wined3d_buffer_vk(buffer);
2521 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2522 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2523 buffers[count] = buffer_info->buffer;
2524 offsets[count] = buffer_info->offset + stream->offset;
2525 ++count;
2526 continue;
2529 if (count)
2530 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2531 first = i + 1;
2532 count = 0;
2535 if (count)
2536 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2539 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2540 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2542 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2543 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2544 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2545 const struct wined3d_stream_output *stream;
2546 const VkDescriptorBufferInfo *buffer_info;
2547 struct wined3d_buffer_vk *buffer_vk;
2548 struct wined3d_buffer *buffer;
2549 unsigned int i, first, count;
2551 first = 0;
2552 count = 0;
2553 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2555 stream = &state->stream_output[i];
2557 if ((buffer = stream->buffer))
2559 buffer_vk = wined3d_buffer_vk(buffer);
2560 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2561 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2562 buffers[count] = buffer_info->buffer;
2563 if ((offsets[count] = stream->offset) == ~0u)
2565 FIXME("Appending to stream output buffers not implemented.\n");
2566 offsets[count] = 0;
2568 sizes[count] = buffer_info->range - offsets[count];
2569 offsets[count] += buffer_info->offset;
2570 ++count;
2571 continue;
2574 if (count)
2575 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2576 first = i + 1;
2577 count = 0;
2580 if (count)
2581 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2584 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2585 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2587 struct VkDescriptorPoolCreateInfo pool_desc;
2588 VkResult vr;
2590 static const VkDescriptorPoolSize pool_sizes[] =
2592 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2593 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2594 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2595 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2596 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2597 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2600 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2601 pool_desc.pNext = NULL;
2602 pool_desc.flags = 0;
2603 pool_desc.maxSets = 512;
2604 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2605 pool_desc.pPoolSizes = pool_sizes;
2607 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2608 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2610 return vr;
2613 VkResult wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2614 VkDescriptorSetLayout vk_set_layout, VkDescriptorSet *vk_descriptor_set)
2616 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2617 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2618 struct VkDescriptorSetAllocateInfo set_desc;
2619 VkResult vr;
2621 if (!context_vk->vk_descriptor_pool && (vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk,
2622 vk_info, &context_vk->vk_descriptor_pool)))
2624 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2625 return vr;
2628 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2629 set_desc.pNext = NULL;
2630 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2631 set_desc.descriptorSetCount = 1;
2632 set_desc.pSetLayouts = &vk_set_layout;
2633 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2634 return vr;
2636 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2638 wined3d_context_vk_destroy_vk_descriptor_pool(context_vk,
2639 context_vk->vk_descriptor_pool, context_vk->current_command_buffer.id);
2640 context_vk->vk_descriptor_pool = VK_NULL_HANDLE;
2641 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk, vk_info, &context_vk->vk_descriptor_pool)))
2643 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2644 return vr;
2647 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2648 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2649 return vr;
2652 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2654 return vr;
2657 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2658 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2659 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2660 const VkBufferView *buffer_view)
2662 SIZE_T write_count = writes->count;
2663 VkWriteDescriptorSet *write;
2665 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2666 write_count + 1, sizeof(*writes->writes)))
2667 return false;
2669 write = &writes->writes[write_count];
2670 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2671 write->pNext = NULL;
2672 write->dstSet = vk_descriptor_set;
2673 write->dstBinding = binding_idx;
2674 write->dstArrayElement = 0;
2675 write->descriptorCount = 1;
2676 write->descriptorType = type;
2677 write->pImageInfo = image_info;
2678 write->pBufferInfo = buffer_info;
2679 write->pTexelBufferView = buffer_view;
2681 ++writes->count;
2683 return true;
2686 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2687 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2688 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2690 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2692 switch (type)
2694 case WINED3D_SHADER_RESOURCE_BUFFER:
2695 if (data_type == WINED3D_DATA_FLOAT)
2696 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2697 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2698 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2699 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2701 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2702 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2703 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2705 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2706 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2707 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2709 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2710 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2711 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2713 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2714 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2715 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2717 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2718 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2719 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2721 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2722 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2723 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
2725 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2726 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2727 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2729 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2730 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2731 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2733 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
2734 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2735 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube_array, NULL);
2737 default:
2738 FIXME("Unhandled resource type %#x.\n", type);
2739 return false;
2743 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2744 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2745 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
2747 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
2748 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2749 struct wined3d_buffer_vk *buffer_vk;
2750 struct wined3d_buffer *buffer;
2752 if (!(buffer = cb_state->buffer))
2753 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2754 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
2756 buffer_vk = wined3d_buffer_vk(buffer);
2757 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
2758 buffer_info->offset += cb_state->offset;
2759 buffer_info->range = min(cb_state->size, buffer_info->range);
2760 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2761 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
2762 return false;
2763 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2764 return true;
2767 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2768 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2769 const struct wined3d_shader_resource_binding *binding)
2771 struct wined3d_shader_resource_view_vk *srv_vk;
2772 struct wined3d_shader_resource_view *srv;
2773 const VkDescriptorImageInfo *image_info;
2774 struct wined3d_resource *resource;
2775 struct wined3d_view_vk *view_vk;
2776 VkBufferView *buffer_view;
2777 VkDescriptorType type;
2779 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
2780 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
2781 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
2783 resource = srv->resource;
2784 srv_vk = wined3d_shader_resource_view_vk(srv);
2785 view_vk = &srv_vk->view_vk;
2786 if (resource->type == WINED3D_RTYPE_BUFFER)
2788 image_info = NULL;
2789 buffer_view = &view_vk->u.vk_buffer_view;
2790 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
2792 else
2794 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2796 if (view_vk->u.vk_image_info.imageView)
2797 image_info = &view_vk->u.vk_image_info;
2798 else
2799 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2800 buffer_view = NULL;
2801 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2804 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2805 binding->binding_idx, type, NULL, image_info, buffer_view))
2806 return false;
2807 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
2808 return true;
2811 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
2812 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2813 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2815 struct wined3d_unordered_access_view_vk *uav_vk;
2816 struct wined3d_unordered_access_view *uav;
2817 const VkDescriptorImageInfo *image_info;
2818 struct wined3d_resource *resource;
2819 struct wined3d_view_vk *view_vk;
2820 VkBufferView *buffer_view;
2821 VkDescriptorType type;
2823 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2825 FIXME("NULL unordered access views not implemented.\n");
2826 return false;
2828 resource = uav->resource;
2830 uav_vk = wined3d_unordered_access_view_vk(uav);
2831 view_vk = &uav_vk->view_vk;
2832 if (resource->type == WINED3D_RTYPE_BUFFER)
2834 image_info = NULL;
2835 buffer_view = &view_vk->u.vk_buffer_view;
2836 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2838 else
2840 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2842 if (view_vk->u.vk_image_info.imageView)
2843 image_info = &view_vk->u.vk_image_info;
2844 else
2845 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2846 buffer_view = NULL;
2847 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2850 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2851 binding->binding_idx, type, NULL, image_info, buffer_view))
2852 return false;
2853 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
2854 return true;
2857 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
2858 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
2859 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2860 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2862 struct wined3d_unordered_access_view_vk *uav_vk;
2863 struct wined3d_unordered_access_view *uav;
2865 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2867 FIXME("NULL unordered access view counters not implemented.\n");
2868 return false;
2871 uav_vk = wined3d_unordered_access_view_vk(uav);
2872 if (!uav_vk->vk_counter_view)
2873 return false;
2875 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2876 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
2879 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
2880 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2881 const struct wined3d_shader_resource_binding *binding)
2883 struct wined3d_sampler *sampler;
2885 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
2886 sampler = context_vk->c.device->null_sampler;
2887 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2888 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
2889 return false;
2890 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
2891 return true;
2894 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
2895 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
2897 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
2898 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
2899 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2900 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2901 const struct wined3d_shader_resource_binding *binding;
2902 struct wined3d_shader_resource_bindings *bindings;
2903 VkDescriptorSetLayout vk_set_layout;
2904 VkPipelineLayout vk_pipeline_layout;
2905 VkPipelineBindPoint vk_bind_point;
2906 VkDescriptorSet vk_descriptor_set;
2907 VkResult vr;
2908 size_t i;
2910 switch (pipeline)
2912 case WINED3D_PIPELINE_GRAPHICS:
2913 bindings = &context_vk->graphics.bindings;
2914 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2915 vk_set_layout = context_vk->graphics.vk_set_layout;
2916 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
2917 break;
2919 case WINED3D_PIPELINE_COMPUTE:
2920 bindings = &context_vk->compute.bindings;
2921 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2922 vk_set_layout = context_vk->compute.vk_set_layout;
2923 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
2924 break;
2926 default:
2927 ERR("Invalid pipeline %#x.\n", pipeline);
2928 return false;
2931 if ((vr = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout, &vk_descriptor_set)))
2933 WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2934 return false;
2937 writes->count = 0;
2938 for (i = 0; i < bindings->count; ++i)
2940 binding = &bindings->bindings[i];
2942 switch (binding->shader_descriptor_type)
2944 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
2945 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
2946 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
2947 return false;
2948 break;
2950 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
2951 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
2952 context_vk, vk_descriptor_set, state, binding))
2953 return false;
2954 break;
2956 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
2957 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
2958 context_vk, pipeline, vk_descriptor_set, state, binding))
2959 return false;
2960 break;
2962 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
2963 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
2964 context_vk, pipeline, vk_descriptor_set, state, binding))
2965 return false;
2966 break;
2968 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
2969 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
2970 context_vk, vk_descriptor_set, state, binding))
2971 return false;
2972 break;
2974 default:
2975 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
2976 return false;
2980 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
2981 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
2982 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
2984 return true;
2987 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
2988 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
2989 VkDescriptorSetLayout *vk_set_layout)
2991 VkDescriptorSetLayoutCreateInfo layout_desc;
2992 VkResult vr;
2994 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2995 layout_desc.pNext = NULL;
2996 layout_desc.flags = 0;
2997 layout_desc.bindingCount = key->binding_count;
2998 layout_desc.pBindings = key->bindings;
3000 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
3001 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3003 return vr;
3006 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
3007 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
3009 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3010 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3011 struct wined3d_pipeline_layout_key_vk key;
3012 struct wined3d_pipeline_layout_vk *layout;
3013 VkPipelineLayoutCreateInfo layout_desc;
3014 struct wine_rb_entry *entry;
3015 VkResult vr;
3017 key.bindings = bindings;
3018 key.binding_count = binding_count;
3019 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
3020 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
3022 if (!(layout = heap_alloc(sizeof(*layout))))
3023 return NULL;
3025 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
3027 heap_free(layout);
3028 return NULL;
3030 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
3031 layout->key.binding_count = key.binding_count;
3033 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
3035 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3036 goto fail;
3039 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3040 layout_desc.pNext = NULL;
3041 layout_desc.flags = 0;
3042 layout_desc.setLayoutCount = 1;
3043 layout_desc.pSetLayouts = &layout->vk_set_layout;
3044 layout_desc.pushConstantRangeCount = 0;
3045 layout_desc.pPushConstantRanges = NULL;
3047 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
3048 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
3050 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
3051 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3052 goto fail;
3055 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
3057 ERR("Failed to insert pipeline layout.\n");
3058 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3059 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3060 goto fail;
3063 return layout;
3065 fail:
3066 heap_free(layout->key.bindings);
3067 heap_free(layout);
3068 return NULL;
3071 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3073 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3074 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3075 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3076 struct wined3d_graphics_pipeline_key_vk *key;
3077 struct wine_rb_entry *entry;
3078 VkResult vr;
3080 key = &context_vk->graphics.pipeline_key_vk;
3081 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3082 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3084 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3085 return VK_NULL_HANDLE;
3086 pipeline_vk->key = *key;
3088 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3089 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3091 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3092 heap_free(pipeline_vk);
3093 return VK_NULL_HANDLE;
3096 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3097 ERR("Failed to insert pipeline.\n");
3099 return pipeline_vk->vk_pipeline;
3102 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3103 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3105 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3106 const struct wined3d_shader_resource_bindings *bindings;
3107 const struct wined3d_shader_resource_binding *binding;
3108 struct wined3d_unordered_access_view_vk *uav_vk;
3109 struct wined3d_shader_resource_view_vk *srv_vk;
3110 struct wined3d_unordered_access_view *uav;
3111 struct wined3d_shader_resource_view *srv;
3112 struct wined3d_buffer_vk *buffer_vk;
3113 struct wined3d_sampler *sampler;
3114 struct wined3d_buffer *buffer;
3115 size_t i;
3117 switch (pipeline)
3119 case WINED3D_PIPELINE_GRAPHICS:
3120 bindings = &context_vk->graphics.bindings;
3121 break;
3123 case WINED3D_PIPELINE_COMPUTE:
3124 bindings = &context_vk->compute.bindings;
3125 break;
3127 default:
3128 ERR("Invalid pipeline %#x.\n", pipeline);
3129 return;
3132 writes->count = 0;
3133 for (i = 0; i < bindings->count; ++i)
3135 binding = &bindings->bindings[i];
3137 switch (binding->shader_descriptor_type)
3139 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3140 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3141 break;
3143 buffer_vk = wined3d_buffer_vk(buffer);
3144 wined3d_buffer_load(buffer, &context_vk->c, state);
3145 if (!buffer_vk->b.bo_user.valid)
3147 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3148 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3149 else
3150 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3152 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3153 break;
3155 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3156 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3157 break;
3159 srv_vk = wined3d_shader_resource_view_vk(srv);
3160 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3162 if (!srv_vk->view_vk.bo_user.valid)
3164 wined3d_shader_resource_view_vk_update(srv_vk, context_vk);
3165 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3166 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3167 else
3168 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3170 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3172 else
3174 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3176 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3177 break;
3179 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3180 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3181 break;
3183 uav_vk = wined3d_unordered_access_view_vk(uav);
3184 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3186 if (!uav_vk->view_vk.bo_user.valid)
3188 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3189 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3190 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3191 else
3192 context_invalidate_compute_state(&context_vk->c,
3193 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3195 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3196 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3198 else
3200 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3201 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3203 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3204 break;
3206 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3207 break;
3209 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3210 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3211 sampler = context_vk->c.device->null_sampler;
3212 break;
3214 default:
3215 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3216 break;
3221 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3222 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3224 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3225 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3226 struct wined3d_rendertarget_view *dsv;
3227 struct wined3d_buffer_vk *buffer_vk;
3228 VkSampleCountFlagBits sample_count;
3229 VkCommandBuffer vk_command_buffer;
3230 struct wined3d_buffer *buffer;
3231 uint32_t null_buffer_binding;
3232 unsigned int i;
3234 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3235 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3236 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3237 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3238 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3239 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3240 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3241 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3242 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3243 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3244 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3246 context_vk->sample_count = 0;
3247 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3249 struct wined3d_rendertarget_view *rtv;
3251 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3252 continue;
3254 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3256 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3257 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3259 else
3261 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3264 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3265 if (!context_vk->sample_count)
3266 context_vk->sample_count = sample_count;
3267 else if (context_vk->sample_count != sample_count)
3268 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3271 if ((dsv = state->fb.depth_stencil))
3273 if (wined3d_state_uses_depth_buffer(state))
3274 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3275 else
3276 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3277 if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write)
3278 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3280 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3281 if (!context_vk->sample_count)
3282 context_vk->sample_count = sample_count;
3283 else if (context_vk->sample_count != sample_count)
3284 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3287 if (!context_vk->sample_count)
3288 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3289 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3291 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3292 if (!context_vk->graphics.vk_pipeline_layout)
3294 ERR("No pipeline layout set.\n");
3295 return VK_NULL_HANDLE;
3297 context_vk->c.update_shader_resource_bindings = 1;
3298 context_vk->c.update_unordered_access_view_bindings = 1;
3301 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3303 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3305 if (!(buffer = state->streams[i].buffer))
3306 continue;
3308 buffer_vk = wined3d_buffer_vk(buffer);
3309 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3310 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3311 if (!buffer_vk->b.bo_user.valid)
3312 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3315 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3317 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3319 if (!(buffer = state->stream_output[i].buffer))
3320 continue;
3322 buffer_vk = wined3d_buffer_vk(buffer);
3323 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3324 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3325 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3326 if (!buffer_vk->b.bo_user.valid)
3327 context_vk->update_stream_output = 1;
3329 context_vk->c.transform_feedback_active = 1;
3332 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3334 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3335 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3336 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3337 if (!buffer_vk->b.bo_user.valid)
3338 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3341 if (indirect_vk)
3343 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3344 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3347 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3349 ERR("Failed to get command buffer.\n");
3350 return VK_NULL_HANDLE;
3353 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3354 wined3d_context_vk_end_current_render_pass(context_vk);
3355 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3357 ERR("Failed to begin render pass.\n");
3358 return VK_NULL_HANDLE;
3361 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3362 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3364 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3366 ERR("Failed to get graphics pipeline.\n");
3367 return VK_NULL_HANDLE;
3370 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3371 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3372 if (null_buffer_binding != ~0u)
3374 VkDeviceSize offset = 0;
3375 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3376 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3380 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3382 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3383 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3386 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3387 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3389 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3391 context_vk->update_stream_output = 1;
3392 context_vk->c.transform_feedback_paused = 0;
3394 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3396 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3397 context_vk->update_stream_output = 0;
3400 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3402 const VkDescriptorBufferInfo *buffer_info;
3403 VkIndexType idx_type;
3405 if (state->index_format == WINED3DFMT_R16_UINT)
3406 idx_type = VK_INDEX_TYPE_UINT16;
3407 else
3408 idx_type = VK_INDEX_TYPE_UINT32;
3409 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3410 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3411 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer_vk->b.buffer_object));
3412 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3413 buffer_info->offset + state->index_offset, idx_type));
3416 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3417 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3418 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3419 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3420 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3421 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3422 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3423 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3424 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3425 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3426 context_vk->c.update_shader_resource_bindings = 1;
3427 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3428 context_vk->c.update_unordered_access_view_bindings = 1;
3430 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3432 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3434 ERR("Failed to update shader descriptors.\n");
3435 return VK_NULL_HANDLE;
3438 context_vk->c.update_shader_resource_bindings = 0;
3439 context_vk->c.update_unordered_access_view_bindings = 0;
3442 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3443 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3445 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3446 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3448 return vk_command_buffer;
3451 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3452 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3454 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3455 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3456 VkCommandBuffer vk_command_buffer;
3458 wined3d_context_vk_end_current_render_pass(context_vk);
3460 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3461 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3463 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3465 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3466 if (!context_vk->compute.vk_pipeline)
3468 ERR("No compute pipeline set.\n");
3469 return VK_NULL_HANDLE;
3471 context_vk->c.update_compute_shader_resource_bindings = 1;
3472 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3473 context_vk->update_compute_pipeline = 1;
3476 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3478 if (indirect_vk)
3480 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3481 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3484 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3486 ERR("Failed to get command buffer.\n");
3487 return VK_NULL_HANDLE;
3490 if (context_vk->update_compute_pipeline)
3492 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3493 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3494 context_vk->update_compute_pipeline = 0;
3497 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3498 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3499 context_vk->c.update_compute_shader_resource_bindings = 1;
3500 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3501 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3503 if (context_vk->c.update_compute_shader_resource_bindings
3504 || context_vk->c.update_compute_unordered_access_view_bindings)
3506 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3508 ERR("Failed to update shader descriptors.\n");
3509 return VK_NULL_HANDLE;
3512 context_vk->c.update_compute_shader_resource_bindings = 0;
3513 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3516 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3517 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3519 return vk_command_buffer;
3522 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3524 VkCommandPoolCreateInfo command_pool_info;
3525 const struct wined3d_vk_info *vk_info;
3526 struct wined3d_adapter_vk *adapter_vk;
3527 struct wined3d_device_vk *device_vk;
3528 VkResult vr;
3530 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3532 memset(context_vk, 0, sizeof(*context_vk));
3533 wined3d_context_init(&context_vk->c, swapchain);
3534 device_vk = wined3d_device_vk(swapchain->device);
3535 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3536 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3538 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3539 command_pool_info.pNext = NULL;
3540 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3541 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3542 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3543 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3545 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3546 wined3d_context_cleanup(&context_vk->c);
3547 return E_FAIL;
3549 context_vk->current_command_buffer.id = 1;
3551 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3553 list_init(&context_vk->render_pass_queries);
3554 list_init(&context_vk->active_queries);
3555 list_init(&context_vk->completed_query_pools);
3556 list_init(&context_vk->free_occlusion_query_pools);
3557 list_init(&context_vk->free_timestamp_query_pools);
3558 list_init(&context_vk->free_pipeline_statistics_query_pools);
3559 list_init(&context_vk->free_stream_output_statistics_query_pools);
3561 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3562 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3563 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3564 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3566 return WINED3D_OK;