wined3d: Use wined3d_mask_from_size() in shader_glsl_gather4().
[wine.git] / dlls / wined3d / context_vk.c
blob97c60719489e4239b126327224e88acc5a087caa
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;
1800 int ret;
1802 if ((ret = wined3d_uint32_compare(a->binding_count, b->binding_count)))
1803 return ret;
1804 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1807 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1809 const struct wined3d_graphics_pipeline_key_vk *a = key;
1810 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1811 const struct wined3d_graphics_pipeline_vk, entry)->key;
1812 unsigned int i;
1813 int ret;
1815 if ((ret = wined3d_uint32_compare(a->pipeline_desc.stageCount, b->pipeline_desc.stageCount)))
1816 return ret;
1817 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1819 if ((ret = wined3d_uint64_compare(a->stages[i].module, b->stages[i].module)))
1820 return ret;
1823 if ((ret = wined3d_uint32_compare(a->divisor_desc.vertexBindingDivisorCount,
1824 b->divisor_desc.vertexBindingDivisorCount)))
1825 return ret;
1826 if ((ret = memcmp(a->divisors, b->divisors,
1827 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1828 return ret;
1830 if ((ret = wined3d_uint32_compare(a->input_desc.vertexAttributeDescriptionCount,
1831 b->input_desc.vertexAttributeDescriptionCount)))
1832 return ret;
1833 if ((ret = memcmp(a->attributes, b->attributes,
1834 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1835 return ret;
1836 if ((ret = wined3d_uint32_compare(a->input_desc.vertexBindingDescriptionCount,
1837 b->input_desc.vertexBindingDescriptionCount)))
1838 return ret;
1839 if ((ret = memcmp(a->bindings, b->bindings,
1840 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1841 return ret;
1843 if ((ret = wined3d_uint32_compare(a->ia_desc.topology, b->ia_desc.topology)))
1844 return ret;
1845 if ((ret = wined3d_uint32_compare(a->ia_desc.primitiveRestartEnable, b->ia_desc.primitiveRestartEnable)))
1846 return ret;
1848 if ((ret = wined3d_uint32_compare(a->ts_desc.patchControlPoints, b->ts_desc.patchControlPoints)))
1849 return ret;
1851 if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport))))
1852 return ret;
1854 if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor))))
1855 return ret;
1857 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
1858 return ret;
1860 if ((ret = wined3d_uint32_compare(a->ms_desc.rasterizationSamples, b->ms_desc.rasterizationSamples)))
1861 return ret;
1862 if ((ret = wined3d_uint32_compare(a->ms_desc.alphaToCoverageEnable, b->ms_desc.alphaToCoverageEnable)))
1863 return ret;
1864 if ((ret = wined3d_uint32_compare(a->sample_mask, b->sample_mask)))
1865 return ret;
1867 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
1868 return ret;
1870 if ((ret = wined3d_uint32_compare(a->blend_desc.attachmentCount, b->blend_desc.attachmentCount)))
1871 return ret;
1872 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
1873 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
1874 return ret;
1876 if ((ret = wined3d_uint64_compare(a->pipeline_desc.layout, b->pipeline_desc.layout)))
1877 return ret;
1879 if ((ret = wined3d_uint64_compare(a->pipeline_desc.renderPass, b->pipeline_desc.renderPass)))
1880 return ret;
1882 return 0;
1885 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
1887 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
1888 const struct wined3d_bo_slab_vk_key *k = key;
1889 int ret;
1891 if ((ret = wined3d_uint32_compare(k->memory_type, slab->requested_memory_type)))
1892 return ret;
1893 if ((ret = wined3d_uint32_compare(k->usage, slab->bo.usage)))
1894 return ret;
1895 return wined3d_uint64_compare(k->size, slab->bo.size);
1898 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
1900 struct wined3d_graphics_pipeline_key_vk *key;
1901 VkPipelineShaderStageCreateInfo *stage;
1902 unsigned int i;
1904 static const VkDynamicState dynamic_states[] =
1906 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1907 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
1910 key = &context_vk->graphics.pipeline_key_vk;
1911 memset(key, 0, sizeof(*key));
1913 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
1915 stage = &key->stages[i];
1916 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1917 stage->pName = "main";
1920 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1921 key->input_desc.pVertexBindingDescriptions = key->bindings;
1922 key->input_desc.pVertexAttributeDescriptions = key->attributes;
1924 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1925 key->divisor_desc.pVertexBindingDivisors = key->divisors;
1927 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1929 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1931 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1932 key->vp_desc.viewportCount = 1;
1933 key->vp_desc.pViewports = &key->viewport;
1934 key->vp_desc.scissorCount = 1;
1935 key->vp_desc.pScissors = &key->scissor;
1937 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1938 key->rs_desc.lineWidth = 1.0f;
1940 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1941 key->ms_desc.pSampleMask = &key->sample_mask;
1943 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1944 key->ds_desc.maxDepthBounds = 1.0f;
1946 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1947 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
1948 key->blend_desc.pAttachments = key->blend_attachments;
1949 key->blend_desc.blendConstants[0] = 1.0f;
1950 key->blend_desc.blendConstants[1] = 1.0f;
1951 key->blend_desc.blendConstants[2] = 1.0f;
1952 key->blend_desc.blendConstants[3] = 1.0f;
1954 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1955 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
1956 key->dynamic_desc.pDynamicStates = dynamic_states;
1958 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1959 key->pipeline_desc.pStages = key->stages;
1960 key->pipeline_desc.pVertexInputState = &key->input_desc;
1961 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
1962 key->pipeline_desc.pTessellationState = &key->ts_desc;
1963 key->pipeline_desc.pViewportState = &key->vp_desc;
1964 key->pipeline_desc.pRasterizationState = &key->rs_desc;
1965 key->pipeline_desc.pMultisampleState = &key->ms_desc;
1966 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
1967 key->pipeline_desc.pColorBlendState = &key->blend_desc;
1968 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
1969 key->pipeline_desc.basePipelineIndex = -1;
1972 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
1973 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1975 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
1976 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
1977 const struct wined3d_rasterizer_state_desc *r;
1978 float scale_bias;
1979 union
1981 uint32_t u32;
1982 float f32;
1983 } const_bias;
1985 if (!state->rasterizer_state)
1987 desc->depthClampEnable = VK_FALSE;
1988 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1989 desc->cullMode = VK_CULL_MODE_BACK_BIT;
1990 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
1991 desc->depthBiasEnable = VK_FALSE;
1992 desc->depthBiasConstantFactor = 0.0f;
1993 desc->depthBiasClamp = 0.0f;
1994 desc->depthBiasSlopeFactor = 0.0f;
1996 return;
1999 r = &state->rasterizer_state->desc;
2000 desc->depthClampEnable = !r->depth_clip;
2001 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2002 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
2003 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
2005 scale_bias = r->scale_bias;
2006 const_bias.f32 = r->depth_bias;
2007 if (!scale_bias && !const_bias.f32)
2009 desc->depthBiasEnable = VK_FALSE;
2010 desc->depthBiasConstantFactor = 0.0f;
2011 desc->depthBiasClamp = 0.0f;
2012 desc->depthBiasSlopeFactor = 0.0f;
2014 return;
2017 desc->depthBiasEnable = VK_TRUE;
2018 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
2020 const struct wined3d_rendertarget_view *dsv;
2022 if ((dsv = state->fb.depth_stencil))
2024 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
2025 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
2027 else
2029 desc->depthBiasConstantFactor = 0.0f;
2030 desc->depthBiasSlopeFactor = 0.0f;
2033 else
2035 desc->depthBiasConstantFactor = const_bias.f32;
2036 desc->depthBiasSlopeFactor = scale_bias;
2038 desc->depthBiasClamp = r->depth_bias_clamp;
2041 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
2042 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2044 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
2045 const struct wined3d_blend_state_desc *b;
2046 unsigned int i;
2048 desc->attachmentCount = context_vk->rt_count;
2050 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
2051 if (!state->blend_state)
2053 for (i = 0; i < context_vk->rt_count; ++i)
2055 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
2056 | VK_COLOR_COMPONENT_G_BIT
2057 | VK_COLOR_COMPONENT_B_BIT
2058 | VK_COLOR_COMPONENT_A_BIT;
2061 return;
2064 b = &state->blend_state->desc;
2065 for (i = 0; i < context_vk->rt_count; ++i)
2067 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2068 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2069 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2070 enum wined3d_blend src_blend, dst_blend;
2071 const struct wined3d_format *rt_format;
2073 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2074 if (!rt->enable)
2075 continue;
2077 if (rtv)
2078 rt_format = rtv->format;
2079 else
2080 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2081 a->blendEnable = VK_TRUE;
2083 src_blend = rt->src;
2084 dst_blend = rt->dst;
2085 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2087 src_blend = WINED3D_BLEND_SRCALPHA;
2088 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2090 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2092 src_blend = WINED3D_BLEND_INVSRCALPHA;
2093 dst_blend = WINED3D_BLEND_SRCALPHA;
2095 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2096 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2097 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2099 src_blend = rt->src_alpha;
2100 dst_blend = rt->dst_alpha;
2101 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2102 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2103 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2107 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2109 switch (component_type)
2111 case WINED3D_TYPE_UINT:
2112 return VK_FORMAT_R32G32B32A32_UINT;
2113 case WINED3D_TYPE_INT:
2114 return VK_FORMAT_R32G32B32A32_SINT;
2115 case WINED3D_TYPE_UNKNOWN:
2116 case WINED3D_TYPE_FLOAT:
2117 return VK_FORMAT_R32G32B32A32_SFLOAT;
2119 return VK_FORMAT_UNDEFINED;
2122 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2123 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2125 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2126 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2127 struct wined3d_graphics_pipeline_key_vk *key;
2128 VkPipelineShaderStageCreateInfo *stage;
2129 struct wined3d_stream_info stream_info;
2130 struct wined3d_shader *vertex_shader;
2131 VkPrimitiveTopology vk_topology;
2132 VkShaderModule module;
2133 bool update = false;
2134 uint32_t mask;
2136 *null_buffer_binding = ~0u;
2137 key = &context_vk->graphics.pipeline_key_vk;
2139 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2141 stage_count = 0;
2142 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2144 if (!(module = context_vk->graphics.vk_modules[i]))
2145 continue;
2147 stage = &key->stages[stage_count++];
2148 stage->stage = vk_shader_stage_from_wined3d(i);
2149 stage->module = module;
2152 key->pipeline_desc.stageCount = stage_count;
2154 update = true;
2157 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2158 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2159 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2161 VkVertexInputAttributeDescription *a;
2162 VkVertexInputBindingDescription *b;
2164 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2165 divisor_count = 0;
2166 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2168 VkVertexInputBindingDivisorDescriptionEXT *d;
2169 struct wined3d_stream_info_element *e;
2170 uint32_t binding;
2172 if (!(stream_info.use_map & (1u << i)))
2173 continue;
2175 a = &key->attributes[attribute_count++];
2176 e = &stream_info.elements[i];
2177 binding = e->stream_idx;
2179 a->location = i;
2180 a->binding = binding;
2181 a->format = wined3d_format_vk(e->format)->vk_format;
2182 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2184 if (mask & (1u << binding))
2185 continue;
2186 mask |= 1u << binding;
2188 b = &key->bindings[binding_count++];
2189 b->binding = binding;
2190 b->stride = e->stride;
2191 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2193 if (e->instanced)
2195 d = &key->divisors[divisor_count++];
2196 d->binding = binding;
2197 d->divisor = e->divisor;
2201 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2202 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2204 struct wined3d_shader_signature_element *element;
2205 struct wined3d_shader_signature *signature;
2206 uint32_t null_binding, location;
2208 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2210 if (!state->streams[i].buffer)
2212 null_binding = i;
2213 break;
2217 if (i == ARRAY_SIZE(state->streams))
2219 ERR("No streams left for a null buffer binding.\n");
2221 else
2223 signature = &vertex_shader->input_signature;
2224 for (i = 0; i < signature->element_count; ++i)
2226 element = &signature->elements[i];
2227 location = element->register_idx;
2229 if (!(mask & (1u << location)) || element->sysval_semantic)
2230 continue;
2231 mask &= ~(1u << location);
2233 a = &key->attributes[attribute_count++];
2234 a->location = location;
2235 a->binding = null_binding;
2236 a->format = vk_format_from_component_type(element->component_type);
2237 a->offset = 0;
2240 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2242 b = &key->bindings[binding_count++];
2243 *null_buffer_binding = b->binding = null_binding;
2244 b->stride = 0;
2245 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2250 key->input_desc.pNext = NULL;
2251 key->input_desc.vertexBindingDescriptionCount = binding_count;
2252 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2254 if (divisor_count)
2256 key->input_desc.pNext = &key->divisor_desc;
2257 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2260 update = true;
2263 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2264 if (key->ia_desc.topology != vk_topology)
2266 key->ia_desc.topology = vk_topology;
2267 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2268 && !wined3d_primitive_type_is_list(state->primitive_type);
2270 update = true;
2273 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2275 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2277 update = true;
2280 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2281 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2282 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2284 key->viewport.x = state->viewports[0].x;
2285 key->viewport.y = state->viewports[0].y;
2286 key->viewport.width = state->viewports[0].width;
2287 key->viewport.height = state->viewports[0].height;
2288 key->viewport.minDepth = state->viewports[0].min_z;
2289 key->viewport.maxDepth = state->viewports[0].max_z;
2291 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2293 const RECT *r = &state->scissor_rects[0];
2295 key->scissor.offset.x = r->left;
2296 key->scissor.offset.y = r->top;
2297 key->scissor.extent.width = r->right - r->left;
2298 key->scissor.extent.height = r->bottom - r->top;
2300 else
2302 key->scissor.offset.x = key->viewport.x;
2303 key->scissor.offset.y = key->viewport.y;
2304 key->scissor.extent.width = key->viewport.width;
2305 key->scissor.extent.height = key->viewport.height;
2307 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2308 if (key->scissor.offset.x < 0)
2309 key->scissor.offset.x = 0;
2310 if (key->scissor.offset.y < 0)
2311 key->scissor.offset.y = 0;
2312 key->viewport.y += key->viewport.height;
2313 key->viewport.height = -key->viewport.height;
2315 update = true;
2318 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2319 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2321 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2323 update = true;
2326 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2327 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2329 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2330 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2331 key->sample_mask = state->sample_mask;
2333 update = true;
2336 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2337 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2339 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2341 if (d)
2343 key->ds_desc.depthTestEnable = d->desc.depth;
2344 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2345 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2346 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2347 if (key->ds_desc.stencilTestEnable)
2349 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2350 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2351 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2352 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2353 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2354 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2356 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2357 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2358 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2359 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2360 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2361 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2363 else
2365 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2366 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2369 else
2371 key->ds_desc.depthTestEnable = VK_TRUE;
2372 key->ds_desc.depthWriteEnable = VK_TRUE;
2373 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2374 key->ds_desc.stencilTestEnable = VK_FALSE;
2377 update = true;
2380 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2381 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2383 wined3d_context_vk_update_blend_state(context_vk, state, key);
2385 update = true;
2388 if (key->pipeline_desc.layout != vk_pipeline_layout)
2390 key->pipeline_desc.layout = vk_pipeline_layout;
2392 update = true;
2395 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2397 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2399 update = true;
2402 return update;
2405 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2406 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2408 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2409 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2410 unsigned int fb_width, fb_height, fb_layer_count;
2411 struct wined3d_rendertarget_view_vk *rtv_vk;
2412 struct wined3d_rendertarget_view *view;
2413 const VkPhysicalDeviceLimits *limits;
2414 struct wined3d_query_vk *query_vk;
2415 VkRenderPassBeginInfo begin_info;
2416 unsigned int attachment_count, i;
2417 VkFramebufferCreateInfo fb_desc;
2418 VkResult vr;
2420 if (context_vk->vk_render_pass)
2421 return true;
2423 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2424 fb_width = limits->maxFramebufferWidth;
2425 fb_height = limits->maxFramebufferHeight;
2426 fb_layer_count = limits->maxFramebufferLayers;
2427 attachment_count = 0;
2429 context_vk->rt_count = 0;
2430 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2432 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2433 continue;
2435 rtv_vk = wined3d_rendertarget_view_vk(view);
2436 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2437 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2438 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2440 if (view->width < fb_width)
2441 fb_width = view->width;
2442 if (view->height < fb_height)
2443 fb_height = view->height;
2444 if (view->layer_count < fb_layer_count)
2445 fb_layer_count = view->layer_count;
2446 context_vk->rt_count = i + 1;
2447 ++attachment_count;
2450 if ((view = state->fb.depth_stencil))
2452 rtv_vk = wined3d_rendertarget_view_vk(view);
2453 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2454 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2455 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2457 if (view->width < fb_width)
2458 fb_width = view->width;
2459 if (view->height < fb_height)
2460 fb_height = view->height;
2461 if (view->layer_count < fb_layer_count)
2462 fb_layer_count = view->layer_count;
2463 ++attachment_count;
2466 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2467 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2469 ERR("Failed to get render pass.\n");
2470 return false;
2473 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2474 fb_desc.pNext = NULL;
2475 fb_desc.flags = 0;
2476 fb_desc.renderPass = context_vk->vk_render_pass;
2477 fb_desc.attachmentCount = attachment_count;
2478 fb_desc.pAttachments = vk_views;
2479 fb_desc.width = fb_width;
2480 fb_desc.height = fb_height;
2481 fb_desc.layers = fb_layer_count;
2483 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2485 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2486 return false;
2489 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2490 begin_info.pNext = NULL;
2491 begin_info.renderPass = context_vk->vk_render_pass;
2492 begin_info.framebuffer = context_vk->vk_framebuffer;
2493 begin_info.renderArea.offset.x = 0;
2494 begin_info.renderArea.offset.y = 0;
2495 begin_info.renderArea.extent.width = fb_width;
2496 begin_info.renderArea.extent.height = fb_height;
2497 begin_info.clearValueCount = 0;
2498 begin_info.pClearValues = NULL;
2499 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2501 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2502 wined3d_query_vk_resume(query_vk, context_vk);
2503 return true;
2506 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2507 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2509 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2510 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2511 const struct wined3d_stream_state *stream;
2512 const VkDescriptorBufferInfo *buffer_info;
2513 struct wined3d_buffer_vk *buffer_vk;
2514 struct wined3d_buffer *buffer;
2515 unsigned int i, first, count;
2517 first = 0;
2518 count = 0;
2519 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2521 stream = &state->streams[i];
2523 if ((buffer = stream->buffer))
2525 buffer_vk = wined3d_buffer_vk(buffer);
2526 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2527 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2528 buffers[count] = buffer_info->buffer;
2529 offsets[count] = buffer_info->offset + stream->offset;
2530 ++count;
2531 continue;
2534 if (count)
2535 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2536 first = i + 1;
2537 count = 0;
2540 if (count)
2541 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2544 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2545 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2547 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2548 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2549 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2550 const struct wined3d_stream_output *stream;
2551 const VkDescriptorBufferInfo *buffer_info;
2552 struct wined3d_buffer_vk *buffer_vk;
2553 struct wined3d_buffer *buffer;
2554 unsigned int i, first, count;
2556 first = 0;
2557 count = 0;
2558 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2560 stream = &state->stream_output[i];
2562 if ((buffer = stream->buffer))
2564 buffer_vk = wined3d_buffer_vk(buffer);
2565 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2566 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2567 buffers[count] = buffer_info->buffer;
2568 if ((offsets[count] = stream->offset) == ~0u)
2570 FIXME("Appending to stream output buffers not implemented.\n");
2571 offsets[count] = 0;
2573 sizes[count] = buffer_info->range - offsets[count];
2574 offsets[count] += buffer_info->offset;
2575 ++count;
2576 continue;
2579 if (count)
2580 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2581 first = i + 1;
2582 count = 0;
2585 if (count)
2586 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2589 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2590 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2592 struct VkDescriptorPoolCreateInfo pool_desc;
2593 VkResult vr;
2595 static const VkDescriptorPoolSize pool_sizes[] =
2597 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2598 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2599 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2600 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2601 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2602 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2605 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2606 pool_desc.pNext = NULL;
2607 pool_desc.flags = 0;
2608 pool_desc.maxSets = 512;
2609 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2610 pool_desc.pPoolSizes = pool_sizes;
2612 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2613 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2615 return vr;
2618 VkResult wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2619 VkDescriptorSetLayout vk_set_layout, VkDescriptorSet *vk_descriptor_set)
2621 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2622 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2623 struct VkDescriptorSetAllocateInfo set_desc;
2624 VkResult vr;
2626 if (!context_vk->vk_descriptor_pool && (vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk,
2627 vk_info, &context_vk->vk_descriptor_pool)))
2629 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2630 return vr;
2633 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2634 set_desc.pNext = NULL;
2635 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2636 set_desc.descriptorSetCount = 1;
2637 set_desc.pSetLayouts = &vk_set_layout;
2638 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2639 return vr;
2641 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2643 wined3d_context_vk_destroy_vk_descriptor_pool(context_vk,
2644 context_vk->vk_descriptor_pool, context_vk->current_command_buffer.id);
2645 context_vk->vk_descriptor_pool = VK_NULL_HANDLE;
2646 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk, vk_info, &context_vk->vk_descriptor_pool)))
2648 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2649 return vr;
2652 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2653 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2654 return vr;
2657 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2659 return vr;
2662 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2663 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2664 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2665 const VkBufferView *buffer_view)
2667 SIZE_T write_count = writes->count;
2668 VkWriteDescriptorSet *write;
2670 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2671 write_count + 1, sizeof(*writes->writes)))
2672 return false;
2674 write = &writes->writes[write_count];
2675 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2676 write->pNext = NULL;
2677 write->dstSet = vk_descriptor_set;
2678 write->dstBinding = binding_idx;
2679 write->dstArrayElement = 0;
2680 write->descriptorCount = 1;
2681 write->descriptorType = type;
2682 write->pImageInfo = image_info;
2683 write->pBufferInfo = buffer_info;
2684 write->pTexelBufferView = buffer_view;
2686 ++writes->count;
2688 return true;
2691 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2692 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2693 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2695 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2697 switch (type)
2699 case WINED3D_SHADER_RESOURCE_BUFFER:
2700 if (data_type == WINED3D_DATA_FLOAT)
2701 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2702 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2703 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2704 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2706 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2707 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2708 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2710 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2711 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2712 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2714 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2715 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2716 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2718 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2719 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2720 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2722 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2723 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2724 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2726 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2727 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2728 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
2730 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2731 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2732 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2734 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2735 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2736 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2738 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
2739 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2740 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube_array, NULL);
2742 default:
2743 FIXME("Unhandled resource type %#x.\n", type);
2744 return false;
2748 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2749 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2750 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
2752 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
2753 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2754 struct wined3d_buffer_vk *buffer_vk;
2755 struct wined3d_buffer *buffer;
2757 if (!(buffer = cb_state->buffer))
2758 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2759 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
2761 buffer_vk = wined3d_buffer_vk(buffer);
2762 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
2763 buffer_info->offset += cb_state->offset;
2764 buffer_info->range = min(cb_state->size, buffer_info->range);
2765 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2766 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
2767 return false;
2768 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2769 return true;
2772 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2773 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2774 const struct wined3d_shader_resource_binding *binding)
2776 struct wined3d_shader_resource_view_vk *srv_vk;
2777 struct wined3d_shader_resource_view *srv;
2778 const VkDescriptorImageInfo *image_info;
2779 struct wined3d_resource *resource;
2780 struct wined3d_view_vk *view_vk;
2781 VkBufferView *buffer_view;
2782 VkDescriptorType type;
2784 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
2785 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
2786 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
2788 resource = srv->resource;
2789 srv_vk = wined3d_shader_resource_view_vk(srv);
2790 view_vk = &srv_vk->view_vk;
2791 if (resource->type == WINED3D_RTYPE_BUFFER)
2793 image_info = NULL;
2794 buffer_view = &view_vk->u.vk_buffer_view;
2795 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
2797 else
2799 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2801 if (view_vk->u.vk_image_info.imageView)
2802 image_info = &view_vk->u.vk_image_info;
2803 else
2804 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2805 buffer_view = NULL;
2806 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2809 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2810 binding->binding_idx, type, NULL, image_info, buffer_view))
2811 return false;
2812 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
2813 return true;
2816 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
2817 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2818 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2820 struct wined3d_unordered_access_view_vk *uav_vk;
2821 struct wined3d_unordered_access_view *uav;
2822 const VkDescriptorImageInfo *image_info;
2823 struct wined3d_resource *resource;
2824 struct wined3d_view_vk *view_vk;
2825 VkBufferView *buffer_view;
2826 VkDescriptorType type;
2828 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2830 FIXME("NULL unordered access views not implemented.\n");
2831 return false;
2833 resource = uav->resource;
2835 uav_vk = wined3d_unordered_access_view_vk(uav);
2836 view_vk = &uav_vk->view_vk;
2837 if (resource->type == WINED3D_RTYPE_BUFFER)
2839 image_info = NULL;
2840 buffer_view = &view_vk->u.vk_buffer_view;
2841 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2843 else
2845 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2847 if (view_vk->u.vk_image_info.imageView)
2848 image_info = &view_vk->u.vk_image_info;
2849 else
2850 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2851 buffer_view = NULL;
2852 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2855 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2856 binding->binding_idx, type, NULL, image_info, buffer_view))
2857 return false;
2858 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
2859 return true;
2862 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
2863 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
2864 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2865 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2867 struct wined3d_unordered_access_view_vk *uav_vk;
2868 struct wined3d_unordered_access_view *uav;
2870 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2872 FIXME("NULL unordered access view counters not implemented.\n");
2873 return false;
2876 uav_vk = wined3d_unordered_access_view_vk(uav);
2877 if (!uav_vk->vk_counter_view)
2878 return false;
2880 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2881 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
2884 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
2885 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2886 const struct wined3d_shader_resource_binding *binding)
2888 struct wined3d_sampler *sampler;
2890 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
2891 sampler = context_vk->c.device->null_sampler;
2892 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2893 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
2894 return false;
2895 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
2896 return true;
2899 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
2900 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
2902 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
2903 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
2904 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2905 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2906 const struct wined3d_shader_resource_binding *binding;
2907 struct wined3d_shader_resource_bindings *bindings;
2908 VkDescriptorSetLayout vk_set_layout;
2909 VkPipelineLayout vk_pipeline_layout;
2910 VkPipelineBindPoint vk_bind_point;
2911 VkDescriptorSet vk_descriptor_set;
2912 VkResult vr;
2913 size_t i;
2915 switch (pipeline)
2917 case WINED3D_PIPELINE_GRAPHICS:
2918 bindings = &context_vk->graphics.bindings;
2919 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2920 vk_set_layout = context_vk->graphics.vk_set_layout;
2921 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
2922 break;
2924 case WINED3D_PIPELINE_COMPUTE:
2925 bindings = &context_vk->compute.bindings;
2926 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2927 vk_set_layout = context_vk->compute.vk_set_layout;
2928 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
2929 break;
2931 default:
2932 ERR("Invalid pipeline %#x.\n", pipeline);
2933 return false;
2936 if ((vr = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout, &vk_descriptor_set)))
2938 WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2939 return false;
2942 writes->count = 0;
2943 for (i = 0; i < bindings->count; ++i)
2945 binding = &bindings->bindings[i];
2947 switch (binding->shader_descriptor_type)
2949 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
2950 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
2951 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
2952 return false;
2953 break;
2955 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
2956 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
2957 context_vk, vk_descriptor_set, state, binding))
2958 return false;
2959 break;
2961 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
2962 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
2963 context_vk, pipeline, vk_descriptor_set, state, binding))
2964 return false;
2965 break;
2967 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
2968 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
2969 context_vk, pipeline, vk_descriptor_set, state, binding))
2970 return false;
2971 break;
2973 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
2974 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
2975 context_vk, vk_descriptor_set, state, binding))
2976 return false;
2977 break;
2979 default:
2980 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
2981 return false;
2985 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
2986 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
2987 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
2989 return true;
2992 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
2993 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
2994 VkDescriptorSetLayout *vk_set_layout)
2996 VkDescriptorSetLayoutCreateInfo layout_desc;
2997 VkResult vr;
2999 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3000 layout_desc.pNext = NULL;
3001 layout_desc.flags = 0;
3002 layout_desc.bindingCount = key->binding_count;
3003 layout_desc.pBindings = key->bindings;
3005 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
3006 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3008 return vr;
3011 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
3012 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
3014 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3015 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3016 struct wined3d_pipeline_layout_key_vk key;
3017 struct wined3d_pipeline_layout_vk *layout;
3018 VkPipelineLayoutCreateInfo layout_desc;
3019 struct wine_rb_entry *entry;
3020 VkResult vr;
3022 key.bindings = bindings;
3023 key.binding_count = binding_count;
3024 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
3025 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
3027 if (!(layout = heap_alloc(sizeof(*layout))))
3028 return NULL;
3030 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
3032 heap_free(layout);
3033 return NULL;
3035 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
3036 layout->key.binding_count = key.binding_count;
3038 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
3040 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3041 goto fail;
3044 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3045 layout_desc.pNext = NULL;
3046 layout_desc.flags = 0;
3047 layout_desc.setLayoutCount = 1;
3048 layout_desc.pSetLayouts = &layout->vk_set_layout;
3049 layout_desc.pushConstantRangeCount = 0;
3050 layout_desc.pPushConstantRanges = NULL;
3052 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
3053 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
3055 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
3056 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3057 goto fail;
3060 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
3062 ERR("Failed to insert pipeline layout.\n");
3063 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3064 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3065 goto fail;
3068 return layout;
3070 fail:
3071 heap_free(layout->key.bindings);
3072 heap_free(layout);
3073 return NULL;
3076 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3078 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3079 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3080 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3081 struct wined3d_graphics_pipeline_key_vk *key;
3082 struct wine_rb_entry *entry;
3083 VkResult vr;
3085 key = &context_vk->graphics.pipeline_key_vk;
3086 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3087 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3089 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3090 return VK_NULL_HANDLE;
3091 pipeline_vk->key = *key;
3093 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3094 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3096 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3097 heap_free(pipeline_vk);
3098 return VK_NULL_HANDLE;
3101 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3102 ERR("Failed to insert pipeline.\n");
3104 return pipeline_vk->vk_pipeline;
3107 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3108 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3110 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3111 const struct wined3d_shader_resource_bindings *bindings;
3112 const struct wined3d_shader_resource_binding *binding;
3113 struct wined3d_unordered_access_view_vk *uav_vk;
3114 struct wined3d_shader_resource_view_vk *srv_vk;
3115 struct wined3d_unordered_access_view *uav;
3116 struct wined3d_shader_resource_view *srv;
3117 struct wined3d_buffer_vk *buffer_vk;
3118 struct wined3d_sampler *sampler;
3119 struct wined3d_buffer *buffer;
3120 size_t i;
3122 switch (pipeline)
3124 case WINED3D_PIPELINE_GRAPHICS:
3125 bindings = &context_vk->graphics.bindings;
3126 break;
3128 case WINED3D_PIPELINE_COMPUTE:
3129 bindings = &context_vk->compute.bindings;
3130 break;
3132 default:
3133 ERR("Invalid pipeline %#x.\n", pipeline);
3134 return;
3137 writes->count = 0;
3138 for (i = 0; i < bindings->count; ++i)
3140 binding = &bindings->bindings[i];
3142 switch (binding->shader_descriptor_type)
3144 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3145 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3146 break;
3148 buffer_vk = wined3d_buffer_vk(buffer);
3149 wined3d_buffer_load(buffer, &context_vk->c, state);
3150 if (!buffer_vk->b.bo_user.valid)
3152 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3153 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3154 else
3155 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3157 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3158 break;
3160 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3161 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3162 break;
3164 srv_vk = wined3d_shader_resource_view_vk(srv);
3165 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3167 if (!srv_vk->view_vk.bo_user.valid)
3169 wined3d_shader_resource_view_vk_update(srv_vk, context_vk);
3170 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3171 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3172 else
3173 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3175 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3177 else
3179 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3181 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3182 break;
3184 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3185 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3186 break;
3188 uav_vk = wined3d_unordered_access_view_vk(uav);
3189 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3191 if (!uav_vk->view_vk.bo_user.valid)
3193 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3194 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3195 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3196 else
3197 context_invalidate_compute_state(&context_vk->c,
3198 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3200 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3201 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3203 else
3205 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3206 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3208 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3209 break;
3211 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3212 break;
3214 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3215 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3216 sampler = context_vk->c.device->null_sampler;
3217 break;
3219 default:
3220 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3221 break;
3226 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3227 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3229 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3230 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3231 struct wined3d_rendertarget_view *dsv;
3232 struct wined3d_buffer_vk *buffer_vk;
3233 VkSampleCountFlagBits sample_count;
3234 VkCommandBuffer vk_command_buffer;
3235 struct wined3d_buffer *buffer;
3236 uint32_t null_buffer_binding;
3237 unsigned int i;
3239 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3240 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3241 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3242 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3243 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3244 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3245 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3246 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3247 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3248 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3249 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3251 context_vk->sample_count = 0;
3252 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3254 struct wined3d_rendertarget_view *rtv;
3256 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3257 continue;
3259 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3261 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3262 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3264 else
3266 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3269 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3270 if (!context_vk->sample_count)
3271 context_vk->sample_count = sample_count;
3272 else if (context_vk->sample_count != sample_count)
3273 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3276 if ((dsv = state->fb.depth_stencil))
3278 if (wined3d_state_uses_depth_buffer(state))
3279 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3280 else
3281 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3282 if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write)
3283 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3285 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3286 if (!context_vk->sample_count)
3287 context_vk->sample_count = sample_count;
3288 else if (context_vk->sample_count != sample_count)
3289 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3292 if (!context_vk->sample_count)
3293 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3294 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3296 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3297 if (!context_vk->graphics.vk_pipeline_layout)
3299 ERR("No pipeline layout set.\n");
3300 return VK_NULL_HANDLE;
3302 context_vk->c.update_shader_resource_bindings = 1;
3303 context_vk->c.update_unordered_access_view_bindings = 1;
3306 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3308 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3310 if (!(buffer = state->streams[i].buffer))
3311 continue;
3313 buffer_vk = wined3d_buffer_vk(buffer);
3314 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3315 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3316 if (!buffer_vk->b.bo_user.valid)
3317 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3320 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3322 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3324 if (!(buffer = state->stream_output[i].buffer))
3325 continue;
3327 buffer_vk = wined3d_buffer_vk(buffer);
3328 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3329 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3330 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3331 if (!buffer_vk->b.bo_user.valid)
3332 context_vk->update_stream_output = 1;
3334 context_vk->c.transform_feedback_active = 1;
3337 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3339 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3340 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3341 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3342 if (!buffer_vk->b.bo_user.valid)
3343 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3346 if (indirect_vk)
3348 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3349 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3352 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3354 ERR("Failed to get command buffer.\n");
3355 return VK_NULL_HANDLE;
3358 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3359 wined3d_context_vk_end_current_render_pass(context_vk);
3360 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3362 ERR("Failed to begin render pass.\n");
3363 return VK_NULL_HANDLE;
3366 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3367 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3369 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3371 ERR("Failed to get graphics pipeline.\n");
3372 return VK_NULL_HANDLE;
3375 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3376 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3377 if (null_buffer_binding != ~0u)
3379 VkDeviceSize offset = 0;
3380 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3381 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3385 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3387 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3388 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3391 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3392 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3394 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3396 context_vk->update_stream_output = 1;
3397 context_vk->c.transform_feedback_paused = 0;
3399 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3401 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3402 context_vk->update_stream_output = 0;
3405 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3407 const VkDescriptorBufferInfo *buffer_info;
3408 VkIndexType idx_type;
3410 if (state->index_format == WINED3DFMT_R16_UINT)
3411 idx_type = VK_INDEX_TYPE_UINT16;
3412 else
3413 idx_type = VK_INDEX_TYPE_UINT32;
3414 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3415 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3416 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer_vk->b.buffer_object));
3417 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3418 buffer_info->offset + state->index_offset, idx_type));
3421 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3422 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3423 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3424 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3425 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3426 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3427 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3428 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3429 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3430 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3431 context_vk->c.update_shader_resource_bindings = 1;
3432 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3433 context_vk->c.update_unordered_access_view_bindings = 1;
3435 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3437 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3439 ERR("Failed to update shader descriptors.\n");
3440 return VK_NULL_HANDLE;
3443 context_vk->c.update_shader_resource_bindings = 0;
3444 context_vk->c.update_unordered_access_view_bindings = 0;
3447 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3448 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3450 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3451 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3453 return vk_command_buffer;
3456 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3457 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3459 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3460 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3461 VkCommandBuffer vk_command_buffer;
3463 wined3d_context_vk_end_current_render_pass(context_vk);
3465 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3466 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3468 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3470 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3471 if (!context_vk->compute.vk_pipeline)
3473 ERR("No compute pipeline set.\n");
3474 return VK_NULL_HANDLE;
3476 context_vk->c.update_compute_shader_resource_bindings = 1;
3477 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3478 context_vk->update_compute_pipeline = 1;
3481 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3483 if (indirect_vk)
3485 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3486 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3489 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3491 ERR("Failed to get command buffer.\n");
3492 return VK_NULL_HANDLE;
3495 if (context_vk->update_compute_pipeline)
3497 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3498 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3499 context_vk->update_compute_pipeline = 0;
3502 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3503 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3504 context_vk->c.update_compute_shader_resource_bindings = 1;
3505 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3506 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3508 if (context_vk->c.update_compute_shader_resource_bindings
3509 || context_vk->c.update_compute_unordered_access_view_bindings)
3511 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3513 ERR("Failed to update shader descriptors.\n");
3514 return VK_NULL_HANDLE;
3517 context_vk->c.update_compute_shader_resource_bindings = 0;
3518 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3521 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3522 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3524 return vk_command_buffer;
3527 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3529 VkCommandPoolCreateInfo command_pool_info;
3530 const struct wined3d_vk_info *vk_info;
3531 struct wined3d_adapter_vk *adapter_vk;
3532 struct wined3d_device_vk *device_vk;
3533 VkResult vr;
3535 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3537 memset(context_vk, 0, sizeof(*context_vk));
3538 wined3d_context_init(&context_vk->c, swapchain);
3539 device_vk = wined3d_device_vk(swapchain->device);
3540 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3541 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3543 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3544 command_pool_info.pNext = NULL;
3545 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3546 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3547 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3548 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3550 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3551 wined3d_context_cleanup(&context_vk->c);
3552 return E_FAIL;
3554 context_vk->current_command_buffer.id = 1;
3556 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3558 list_init(&context_vk->render_pass_queries);
3559 list_init(&context_vk->active_queries);
3560 list_init(&context_vk->completed_query_pools);
3561 list_init(&context_vk->free_occlusion_query_pools);
3562 list_init(&context_vk->free_timestamp_query_pools);
3563 list_init(&context_vk->free_pipeline_statistics_query_pools);
3564 list_init(&context_vk->free_stream_output_statistics_query_pools);
3566 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3567 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3568 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3569 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3571 return WINED3D_OK;