mf/tests: Test input type for WMA decoder DMO.
[wine.git] / dlls / wined3d / context_vk.c
blob8c021a66bc7c6e23ee86ecee273dcf2a6afd7d2f
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 "wined3d_private.h"
27 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
29 VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op)
31 switch (op)
33 case WINED3D_CMP_NEVER:
34 return VK_COMPARE_OP_NEVER;
35 case WINED3D_CMP_LESS:
36 return VK_COMPARE_OP_LESS;
37 case WINED3D_CMP_EQUAL:
38 return VK_COMPARE_OP_EQUAL;
39 case WINED3D_CMP_LESSEQUAL:
40 return VK_COMPARE_OP_LESS_OR_EQUAL;
41 case WINED3D_CMP_GREATER:
42 return VK_COMPARE_OP_GREATER;
43 case WINED3D_CMP_NOTEQUAL:
44 return VK_COMPARE_OP_NOT_EQUAL;
45 case WINED3D_CMP_GREATEREQUAL:
46 return VK_COMPARE_OP_GREATER_OR_EQUAL;
47 case WINED3D_CMP_ALWAYS:
48 return VK_COMPARE_OP_ALWAYS;
49 default:
50 if (!op)
51 WARN("Unhandled compare operation %#x.\n", op);
52 else
53 FIXME("Unhandled compare operation %#x.\n", op);
54 return VK_COMPARE_OP_NEVER;
58 VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type)
60 switch (shader_type)
62 case WINED3D_SHADER_TYPE_VERTEX:
63 return VK_SHADER_STAGE_VERTEX_BIT;
64 case WINED3D_SHADER_TYPE_HULL:
65 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
66 case WINED3D_SHADER_TYPE_DOMAIN:
67 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
68 case WINED3D_SHADER_TYPE_GEOMETRY:
69 return VK_SHADER_STAGE_GEOMETRY_BIT;
70 case WINED3D_SHADER_TYPE_PIXEL:
71 return VK_SHADER_STAGE_FRAGMENT_BIT;
72 case WINED3D_SHADER_TYPE_COMPUTE:
73 return VK_SHADER_STAGE_COMPUTE_BIT;
74 default:
75 ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type));
76 return 0;
80 static VkBlendFactor vk_blend_factor_from_wined3d(enum wined3d_blend blend,
81 const struct wined3d_format *dst_format, bool alpha)
83 switch (blend)
85 case WINED3D_BLEND_ZERO:
86 return VK_BLEND_FACTOR_ZERO;
87 case WINED3D_BLEND_ONE:
88 return VK_BLEND_FACTOR_ONE;
89 case WINED3D_BLEND_SRCCOLOR:
90 return VK_BLEND_FACTOR_SRC_COLOR;
91 case WINED3D_BLEND_INVSRCCOLOR:
92 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
93 case WINED3D_BLEND_SRCALPHA:
94 return VK_BLEND_FACTOR_SRC_ALPHA;
95 case WINED3D_BLEND_INVSRCALPHA:
96 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
97 case WINED3D_BLEND_DESTALPHA:
98 if (dst_format->alpha_size)
99 return VK_BLEND_FACTOR_DST_ALPHA;
100 return VK_BLEND_FACTOR_ONE;
101 case WINED3D_BLEND_INVDESTALPHA:
102 if (dst_format->alpha_size)
103 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
104 return VK_BLEND_FACTOR_ZERO;
105 case WINED3D_BLEND_DESTCOLOR:
106 return VK_BLEND_FACTOR_DST_COLOR;
107 case WINED3D_BLEND_INVDESTCOLOR:
108 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
109 case WINED3D_BLEND_SRCALPHASAT:
110 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
111 case WINED3D_BLEND_BLENDFACTOR:
112 if (alpha)
113 return VK_BLEND_FACTOR_CONSTANT_ALPHA;
114 return VK_BLEND_FACTOR_CONSTANT_COLOR;
115 case WINED3D_BLEND_INVBLENDFACTOR:
116 if (alpha)
117 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
118 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
119 case WINED3D_BLEND_SRC1COLOR:
120 return VK_BLEND_FACTOR_SRC1_COLOR;
121 case WINED3D_BLEND_INVSRC1COLOR:
122 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
123 case WINED3D_BLEND_SRC1ALPHA:
124 return VK_BLEND_FACTOR_SRC1_ALPHA;
125 case WINED3D_BLEND_INVSRC1ALPHA:
126 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
127 default:
128 FIXME("Unhandled blend %#x.\n", blend);
129 return VK_BLEND_FACTOR_ZERO;
133 static VkBlendOp vk_blend_op_from_wined3d(enum wined3d_blend_op op)
135 switch (op)
137 case WINED3D_BLEND_OP_ADD:
138 return VK_BLEND_OP_ADD;
139 case WINED3D_BLEND_OP_SUBTRACT:
140 return VK_BLEND_OP_SUBTRACT;
141 case WINED3D_BLEND_OP_REVSUBTRACT:
142 return VK_BLEND_OP_REVERSE_SUBTRACT;
143 case WINED3D_BLEND_OP_MIN:
144 return VK_BLEND_OP_MIN;
145 case WINED3D_BLEND_OP_MAX:
146 return VK_BLEND_OP_MAX;
147 default:
148 FIXME("Unhandled blend op %#x.\n", op);
149 return VK_BLEND_OP_ADD;
153 static VkColorComponentFlags vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask)
155 VkColorComponentFlags vk_mask = 0;
157 if (wined3d_mask & WINED3DCOLORWRITEENABLE_RED)
158 vk_mask |= VK_COLOR_COMPONENT_R_BIT;
159 if (wined3d_mask & WINED3DCOLORWRITEENABLE_GREEN)
160 vk_mask |= VK_COLOR_COMPONENT_G_BIT;
161 if (wined3d_mask & WINED3DCOLORWRITEENABLE_BLUE)
162 vk_mask |= VK_COLOR_COMPONENT_B_BIT;
163 if (wined3d_mask & WINED3DCOLORWRITEENABLE_ALPHA)
164 vk_mask |= VK_COLOR_COMPONENT_A_BIT;
166 return vk_mask;
169 static VkCullModeFlags vk_cull_mode_from_wined3d(enum wined3d_cull mode)
171 switch (mode)
173 case WINED3D_CULL_NONE:
174 return VK_CULL_MODE_NONE;
175 case WINED3D_CULL_FRONT:
176 return VK_CULL_MODE_FRONT_BIT;
177 case WINED3D_CULL_BACK:
178 return VK_CULL_MODE_BACK_BIT;
179 default:
180 FIXME("Unhandled cull mode %#x.\n", mode);
181 return VK_CULL_MODE_NONE;
185 static VkPrimitiveTopology vk_topology_from_wined3d(enum wined3d_primitive_type t)
187 switch (t)
189 case WINED3D_PT_POINTLIST:
190 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
191 case WINED3D_PT_LINELIST:
192 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
193 case WINED3D_PT_LINESTRIP:
194 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
195 case WINED3D_PT_TRIANGLELIST:
196 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
197 case WINED3D_PT_TRIANGLESTRIP:
198 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
199 case WINED3D_PT_TRIANGLEFAN:
200 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
201 case WINED3D_PT_LINELIST_ADJ:
202 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
203 case WINED3D_PT_LINESTRIP_ADJ:
204 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
205 case WINED3D_PT_TRIANGLELIST_ADJ:
206 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
207 case WINED3D_PT_TRIANGLESTRIP_ADJ:
208 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
209 case WINED3D_PT_PATCH:
210 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
211 default:
212 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t));
213 case WINED3D_PT_UNDEFINED:
214 return ~0u;
218 static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op)
220 switch (op)
222 case WINED3D_STENCIL_OP_KEEP:
223 return VK_STENCIL_OP_KEEP;
224 case WINED3D_STENCIL_OP_ZERO:
225 return VK_STENCIL_OP_ZERO;
226 case WINED3D_STENCIL_OP_REPLACE:
227 return VK_STENCIL_OP_REPLACE;
228 case WINED3D_STENCIL_OP_INCR_SAT:
229 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
230 case WINED3D_STENCIL_OP_DECR_SAT:
231 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
232 case WINED3D_STENCIL_OP_INVERT:
233 return VK_STENCIL_OP_INVERT;
234 case WINED3D_STENCIL_OP_INCR:
235 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
236 case WINED3D_STENCIL_OP_DECR:
237 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
238 default:
239 if (!op)
240 WARN("Unhandled stencil operation %#x.\n", op);
241 else
242 FIXME("Unhandled stencil operation %#x.\n", op);
243 return VK_STENCIL_OP_KEEP;
247 static bool wined3d_get_unused_stream_index(const struct wined3d_state *state, uint32_t *index)
249 uint32_t i;
251 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
253 if (!state->streams[i].buffer)
255 *index = i;
256 return true;
260 return false;
263 static void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk)
265 wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
268 static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk)
270 wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
273 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
274 struct wined3d_context_vk *context_vk)
276 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
277 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
278 void *map_ptr;
279 VkResult vr;
281 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
282 wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
284 wined3d_allocator_chunk_vk_lock(chunk_vk);
286 if (!chunk_vk->c.map_ptr)
288 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device,
289 chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
291 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
292 wined3d_allocator_chunk_vk_unlock(chunk_vk);
293 return NULL;
296 adapter_adjust_mapped_memory(device_vk->d.adapter, WINED3D_ALLOCATOR_CHUNK_SIZE);
299 ++chunk_vk->c.map_count;
300 map_ptr = chunk_vk->c.map_ptr;
302 wined3d_allocator_chunk_vk_unlock(chunk_vk);
304 return map_ptr;
307 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
308 struct wined3d_context_vk *context_vk)
310 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
311 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
313 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
315 wined3d_allocator_chunk_vk_lock(chunk_vk);
317 if (--chunk_vk->c.map_count)
319 wined3d_allocator_chunk_vk_unlock(chunk_vk);
320 return;
323 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
324 chunk_vk->c.map_ptr = NULL;
326 wined3d_allocator_chunk_vk_unlock(chunk_vk);
328 adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE);
331 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
332 unsigned int pool, size_t size)
334 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
335 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
336 VkMemoryAllocateInfo allocate_info;
337 VkDeviceMemory vk_memory;
338 VkResult vr;
340 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
341 allocate_info.pNext = NULL;
342 allocate_info.allocationSize = size;
343 allocate_info.memoryTypeIndex = pool;
344 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
346 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
347 return VK_NULL_HANDLE;
350 return vk_memory;
353 static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
354 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
356 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
357 struct wined3d_allocator *allocator = &device_vk->allocator;
358 struct wined3d_allocator_block *block;
360 wined3d_device_vk_allocator_lock(device_vk);
362 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
364 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
365 wined3d_device_vk_allocator_unlock(device_vk);
366 return NULL;
369 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
371 wined3d_device_vk_allocator_unlock(device_vk);
372 *vk_memory = VK_NULL_HANDLE;
373 return NULL;
376 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
378 wined3d_device_vk_allocator_unlock(device_vk);
379 return block;
382 static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block)
384 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
386 assert(block->chunk->allocator == &device_vk->allocator);
387 wined3d_device_vk_allocator_lock(device_vk);
388 wined3d_allocator_block_free(block);
389 wined3d_device_vk_allocator_unlock(device_vk);
392 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
393 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
395 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
396 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
397 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
398 struct wined3d_bo_slab_vk_key key;
399 struct wined3d_bo_slab_vk *slab;
400 struct wine_rb_entry *entry;
401 size_t object_size, idx;
402 size_t alignment;
404 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
405 return false;
407 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
408 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
409 && limits->minTexelBufferOffsetAlignment > alignment)
410 alignment = limits->minTexelBufferOffsetAlignment;
411 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
412 alignment = limits->minUniformBufferOffsetAlignment;
413 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
414 alignment = limits->minStorageBufferOffsetAlignment;
416 object_size = (size + (alignment - 1)) & ~(alignment - 1);
417 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
418 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
419 key.memory_type = memory_type;
420 key.usage = usage;
421 key.size = 32 * object_size;
423 wined3d_device_vk_allocator_lock(device_vk);
425 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
427 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
428 TRACE("Using existing bo slab %p.\n", slab);
430 else
432 if (!(slab = heap_alloc_zero(sizeof(*slab))))
434 wined3d_device_vk_allocator_unlock(device_vk);
435 ERR("Failed to allocate bo slab.\n");
436 return false;
439 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
441 wined3d_device_vk_allocator_unlock(device_vk);
442 ERR("Failed to add slab to available tree.\n");
443 heap_free(slab);
444 return false;
447 slab->requested_memory_type = memory_type;
448 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
450 wined3d_device_vk_allocator_unlock(device_vk);
451 ERR("Failed to create slab bo.\n");
452 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
453 heap_free(slab);
454 return false;
456 slab->map = ~0u;
458 TRACE("Created new bo slab %p.\n", slab);
461 idx = wined3d_bit_scan(&slab->map);
462 if (!slab->map)
464 if (slab->next)
466 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
467 slab->next = NULL;
469 else
471 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
475 wined3d_device_vk_allocator_unlock(device_vk);
477 *bo = slab->bo;
478 bo->memory = NULL;
479 bo->slab = slab;
480 bo->b.client_map_count = 0;
481 bo->b.map_ptr = NULL;
482 bo->b.buffer_offset = idx * object_size;
483 bo->b.memory_offset = slab->bo.b.memory_offset + bo->b.buffer_offset;
484 bo->size = size;
485 list_init(&bo->b.users);
486 bo->command_buffer_id = 0;
487 bo->host_synced = false;
489 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
490 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
491 wine_dbgstr_longlong(bo->b.buffer_offset), bo);
493 return true;
496 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
497 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
499 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
500 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
501 VkMemoryRequirements memory_requirements;
502 struct wined3d_adapter_vk *adapter_vk;
503 VkBufferCreateInfo create_info;
504 unsigned int memory_type_idx;
505 VkResult vr;
507 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
508 return TRUE;
510 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
512 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
513 create_info.pNext = NULL;
514 create_info.flags = 0;
515 create_info.size = size;
516 create_info.usage = usage;
517 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
518 create_info.queueFamilyIndexCount = 0;
519 create_info.pQueueFamilyIndices = NULL;
521 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
523 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
524 return FALSE;
527 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
529 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
530 memory_requirements.memoryTypeBits, memory_type);
531 if (memory_type_idx == ~0u)
533 ERR("Failed to find suitable memory type.\n");
534 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
535 return FALSE;
537 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
538 memory_type_idx, memory_requirements.size, &bo->vk_memory);
539 if (!bo->vk_memory)
541 ERR("Failed to allocate buffer memory.\n");
542 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
543 return FALSE;
545 bo->b.memory_offset = bo->memory ? bo->memory->offset : 0;
547 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
548 bo->vk_memory, bo->b.memory_offset))) < 0)
550 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
551 if (bo->memory)
552 wined3d_context_vk_free_memory(context_vk, bo->memory);
553 else
554 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
555 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
556 return FALSE;
559 bo->b.client_map_count = 0;
560 bo->b.map_ptr = NULL;
561 bo->b.buffer_offset = 0;
562 bo->size = size;
563 bo->usage = usage;
564 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
565 bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
566 list_init(&bo->b.users);
567 bo->command_buffer_id = 0;
568 bo->slab = NULL;
569 bo->host_synced = false;
571 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
572 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
574 return TRUE;
577 BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkImageType vk_image_type,
578 VkImageUsageFlags usage, VkFormat vk_format, unsigned int width, unsigned int height, unsigned int depth,
579 unsigned int sample_count, unsigned int mip_levels, unsigned int layer_count, unsigned int flags,
580 struct wined3d_image_vk *image)
582 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
583 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
584 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
585 VkMemoryRequirements memory_requirements;
586 VkImageCreateInfo create_info;
587 unsigned int memory_type_idx;
588 VkResult vr;
590 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
591 create_info.pNext = NULL;
592 create_info.flags = flags;
593 create_info.imageType = vk_image_type;
594 create_info.format = vk_format;
595 create_info.extent.width = width;
596 create_info.extent.height = height;
597 create_info.extent.depth = depth;
598 create_info.mipLevels = mip_levels;
599 create_info.arrayLayers = layer_count;
600 create_info.samples = sample_count;
601 create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
602 create_info.usage = usage;
603 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
604 create_info.queueFamilyIndexCount = 0;
605 create_info.pQueueFamilyIndices = NULL;
606 create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
608 image->command_buffer_id = 0;
610 vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &image->vk_image));
611 if (vr != VK_SUCCESS)
613 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr));
614 image->vk_image = VK_NULL_HANDLE;
615 return FALSE;
618 VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image,
619 &memory_requirements));
621 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
622 memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
623 if (memory_type_idx == ~0u)
625 ERR("Failed to find suitable image memory type.\n");
626 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
627 image->vk_image = VK_NULL_HANDLE;
628 return FALSE;
631 image->memory = wined3d_context_vk_allocate_memory(context_vk, memory_type_idx,
632 memory_requirements.size, &image->vk_memory);
633 if (!image->vk_memory)
635 ERR("Failed to allocate image memory.\n");
636 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
637 image->vk_image = VK_NULL_HANDLE;
638 return FALSE;
641 vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, image->vk_memory,
642 image->memory ? image->memory->offset : 0));
643 if (vr != VK_SUCCESS)
645 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
646 if (image->memory)
647 wined3d_context_vk_free_memory(context_vk, image->memory);
648 else
649 VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
650 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
651 image->memory = NULL;
652 image->vk_memory = VK_NULL_HANDLE;
653 image->vk_image = VK_NULL_HANDLE;
654 return FALSE;
657 return TRUE;
660 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
662 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
663 struct wined3d_retired_object_vk *o;
665 if (retired->free)
667 o = retired->free;
668 retired->free = o->u.next;
669 return o;
672 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
673 retired->count + 1, sizeof(*retired->objects)))
674 return NULL;
676 return &retired->objects[retired->count++];
679 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk *context_vk,
680 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
682 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
683 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
684 struct wined3d_retired_object_vk *o;
686 if (context_vk->completed_command_buffer_id >= command_buffer_id)
688 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
689 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
690 return;
693 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
695 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
696 return;
699 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
700 o->u.vk_framebuffer = vk_framebuffer;
701 o->command_buffer_id = command_buffer_id;
704 static void wined3d_context_vk_return_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
705 VkDescriptorPool vk_descriptor_pool)
707 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
708 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
710 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
711 context_vk->vk_descriptor_pool_count + 1, sizeof(*context_vk->vk_descriptor_pools)))
713 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
714 TRACE("Destroying descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
715 return;
718 VK_CALL(vkResetDescriptorPool(device_vk->vk_device, vk_descriptor_pool, 0));
719 context_vk->vk_descriptor_pools[context_vk->vk_descriptor_pool_count++] = vk_descriptor_pool;
722 static void wined3d_context_vk_reset_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
723 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
725 struct wined3d_retired_object_vk *o;
727 if (context_vk->completed_command_buffer_id >= command_buffer_id)
729 wined3d_context_vk_return_vk_descriptor_pool(context_vk, vk_descriptor_pool);
730 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
731 return;
734 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
736 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
737 return;
740 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
741 o->u.vk_descriptor_pool = vk_descriptor_pool;
742 o->command_buffer_id = command_buffer_id;
745 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
746 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
748 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
749 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
750 struct wined3d_retired_object_vk *o;
752 if (context_vk->completed_command_buffer_id >= command_buffer_id)
754 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
755 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
756 return;
759 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
761 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
762 return;
765 o->type = WINED3D_RETIRED_MEMORY_VK;
766 o->u.vk_memory = vk_memory;
767 o->command_buffer_id = command_buffer_id;
770 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
771 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
773 struct wined3d_retired_object_vk *o;
775 if (context_vk->completed_command_buffer_id >= command_buffer_id)
777 wined3d_context_vk_free_memory(context_vk, block);
778 TRACE("Freed block %p.\n", block);
779 return;
782 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
784 ERR("Leaking block %p.\n", block);
785 return;
788 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
789 o->u.block = block;
790 o->command_buffer_id = command_buffer_id;
793 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
794 SIZE_T idx, struct wined3d_context_vk *context_vk)
796 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
797 struct wined3d_bo_slab_vk_key key;
798 struct wine_rb_entry *entry;
800 TRACE("slab %p, idx %Iu, context_vk %p.\n", slab, idx, context_vk);
802 wined3d_device_vk_allocator_lock(device_vk);
804 if (!slab->map)
806 key.memory_type = slab->requested_memory_type;
807 key.usage = slab->bo.usage;
808 key.size = slab->bo.size;
810 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
812 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
813 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
815 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
817 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
820 slab->map |= 1u << idx;
822 wined3d_device_vk_allocator_unlock(device_vk);
825 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
826 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
828 struct wined3d_retired_object_vk *o;
830 if (context_vk->completed_command_buffer_id >= command_buffer_id)
832 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
833 return;
836 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
838 ERR("Leaking slab %p, slice %#Ix.\n", slab, idx);
839 return;
842 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
843 o->u.slice.slab = slab;
844 o->u.slice.idx = idx;
845 o->command_buffer_id = command_buffer_id;
848 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk *context_vk,
849 VkBuffer vk_buffer, uint64_t command_buffer_id)
851 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
852 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
853 struct wined3d_retired_object_vk *o;
855 if (context_vk->completed_command_buffer_id >= command_buffer_id)
857 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
858 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
859 return;
862 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
864 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
865 return;
868 o->type = WINED3D_RETIRED_BUFFER_VK;
869 o->u.vk_buffer = vk_buffer;
870 o->command_buffer_id = command_buffer_id;
873 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk *context_vk,
874 VkImage vk_image, uint64_t command_buffer_id)
876 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
877 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
878 struct wined3d_retired_object_vk *o;
880 if (context_vk->completed_command_buffer_id >= command_buffer_id)
882 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
883 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
884 return;
887 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
889 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
890 return;
893 o->type = WINED3D_RETIRED_IMAGE_VK;
894 o->u.vk_image = vk_image;
895 o->command_buffer_id = command_buffer_id;
898 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk *context_vk,
899 VkBufferView vk_view, uint64_t command_buffer_id)
901 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
902 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
903 struct wined3d_retired_object_vk *o;
905 if (context_vk->completed_command_buffer_id >= command_buffer_id)
907 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
908 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
909 return;
912 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
914 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
915 return;
918 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
919 o->u.vk_buffer_view = vk_view;
920 o->command_buffer_id = command_buffer_id;
923 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk *context_vk,
924 VkImageView vk_view, uint64_t command_buffer_id)
926 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
927 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
928 struct wined3d_retired_object_vk *o;
930 if (context_vk->completed_command_buffer_id >= command_buffer_id)
932 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
933 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
934 return;
937 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
939 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
940 return;
943 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
944 o->u.vk_image_view = vk_view;
945 o->command_buffer_id = command_buffer_id;
948 static void wined3d_context_vk_reset_completed_queries(struct wined3d_context_vk *context_vk,
949 struct wined3d_query_pool_vk *pool_vk, struct wined3d_command_buffer_vk *buffer)
951 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
952 struct wined3d_retired_object_vk *o;
953 struct wined3d_range range;
954 unsigned int start = 0;
956 for (;;)
958 if (!wined3d_bitmap_get_range(pool_vk->completed, WINED3D_QUERY_POOL_SIZE, start, &range))
959 break;
961 VK_CALL(vkCmdResetQueryPool(buffer->vk_command_buffer, pool_vk->vk_query_pool, range.offset, range.size));
963 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
965 ERR("Freeing query range %u+%u in pool %p.\n", range.offset, range.size, pool_vk);
966 wined3d_query_pool_vk_mark_free(context_vk, pool_vk, range.offset, range.size);
968 else
970 o->type = WINED3D_RETIRED_QUERY_POOL_VK;
971 o->u.queries.pool_vk = pool_vk;
972 o->u.queries.start = range.offset;
973 o->u.queries.count = range.size;
974 o->command_buffer_id = buffer->id;
977 start = range.offset + range.size;
980 memset(pool_vk->completed, 0, sizeof(pool_vk->completed));
983 void wined3d_context_vk_destroy_vk_pipeline(struct wined3d_context_vk *context_vk,
984 VkPipeline vk_pipeline, uint64_t command_buffer_id)
986 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
987 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
988 struct wined3d_retired_object_vk *o;
990 if (context_vk->completed_command_buffer_id >= command_buffer_id)
992 VK_CALL(vkDestroyPipeline(device_vk->vk_device, vk_pipeline, NULL));
993 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
994 return;
997 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
999 ERR("Leaking pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
1000 return;
1003 o->type = WINED3D_RETIRED_PIPELINE_VK;
1004 o->u.vk_pipeline = vk_pipeline;
1005 o->command_buffer_id = command_buffer_id;
1009 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
1010 VkSampler vk_sampler, uint64_t command_buffer_id)
1012 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1013 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1014 struct wined3d_retired_object_vk *o;
1016 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1018 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
1019 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1020 return;
1023 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1025 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1026 return;
1029 o->type = WINED3D_RETIRED_SAMPLER_VK;
1030 o->u.vk_sampler = vk_sampler;
1031 o->command_buffer_id = command_buffer_id;
1034 void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk,
1035 VkEvent vk_event, uint64_t command_buffer_id)
1037 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1038 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1039 struct wined3d_retired_object_vk *o;
1041 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1043 VK_CALL(vkDestroyEvent(device_vk->vk_device, vk_event, NULL));
1044 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1045 return;
1048 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1050 ERR("Leaking event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1051 return;
1054 o->type = WINED3D_RETIRED_EVENT_VK;
1055 o->u.vk_event = vk_event;
1056 o->command_buffer_id = command_buffer_id;
1059 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
1061 wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
1062 if (image->memory)
1063 wined3d_context_vk_destroy_allocator_block(context_vk, image->memory,
1064 image->command_buffer_id);
1065 else
1066 wined3d_context_vk_destroy_vk_memory(context_vk, image->vk_memory, image->command_buffer_id);
1068 image->vk_image = VK_NULL_HANDLE;
1069 image->vk_memory = VK_NULL_HANDLE;
1070 image->memory = NULL;
1073 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
1075 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1076 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1077 struct wined3d_bo_slab_vk *slab_vk;
1078 size_t object_size, idx;
1080 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
1082 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
1083 context_vk->retired_bo_size += bo->size;
1085 if ((slab_vk = bo->slab))
1087 if (bo->b.map_ptr)
1088 wined3d_bo_slab_vk_unmap(slab_vk, context_vk);
1089 object_size = slab_vk->bo.size / 32;
1090 idx = bo->b.buffer_offset / object_size;
1091 wined3d_context_vk_destroy_bo_slab_slice(context_vk, slab_vk, idx, bo->command_buffer_id);
1092 return;
1095 wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
1096 if (bo->memory)
1098 if (bo->b.map_ptr)
1099 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
1100 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
1101 return;
1104 if (bo->b.map_ptr)
1106 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
1107 adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size);
1109 wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
1112 static void wined3d_context_vk_remove_command_buffer(struct wined3d_context_vk *context_vk,
1113 unsigned int submit_index)
1115 struct wined3d_command_buffer_vk *buffer = &context_vk->submitted.buffers[submit_index];
1116 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1117 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1119 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
1120 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1121 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1123 if (buffer->id > context_vk->completed_command_buffer_id)
1124 context_vk->completed_command_buffer_id = buffer->id;
1125 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
1128 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk, VkFence vk_fence)
1130 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1131 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
1132 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1133 struct wined3d_command_buffer_vk *buffer;
1134 struct wined3d_retired_object_vk *o;
1135 uint64_t command_buffer_id;
1136 SIZE_T i = 0;
1138 while (i < context_vk->submitted.buffer_count)
1140 buffer = &context_vk->submitted.buffers[i];
1141 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
1143 ++i;
1144 continue;
1147 TRACE("Command buffer %p with id 0x%s has finished.\n",
1148 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1149 if (buffer->vk_fence == vk_fence)
1150 return;
1151 wined3d_context_vk_remove_command_buffer(context_vk, i);
1154 command_buffer_id = context_vk->completed_command_buffer_id;
1156 retired->free = NULL;
1157 for (i = retired->count; i; --i)
1159 o = &retired->objects[i - 1];
1161 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
1162 continue;
1164 switch (o->type)
1166 case WINED3D_RETIRED_FREE_VK:
1167 /* Nothing to do. */
1168 break;
1170 case WINED3D_RETIRED_FRAMEBUFFER_VK:
1171 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
1172 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
1173 break;
1175 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
1176 wined3d_context_vk_return_vk_descriptor_pool(context_vk, o->u.vk_descriptor_pool);
1177 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
1178 break;
1180 case WINED3D_RETIRED_MEMORY_VK:
1181 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
1182 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
1183 break;
1185 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
1186 TRACE("Destroying block %p.\n", o->u.block);
1187 wined3d_context_vk_free_memory(context_vk, o->u.block);
1188 break;
1190 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
1191 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
1192 break;
1194 case WINED3D_RETIRED_BUFFER_VK:
1195 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
1196 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
1197 break;
1199 case WINED3D_RETIRED_IMAGE_VK:
1200 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
1201 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
1202 break;
1204 case WINED3D_RETIRED_BUFFER_VIEW_VK:
1205 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
1206 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
1207 break;
1209 case WINED3D_RETIRED_IMAGE_VIEW_VK:
1210 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
1211 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
1212 break;
1214 case WINED3D_RETIRED_SAMPLER_VK:
1215 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
1216 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
1217 break;
1219 case WINED3D_RETIRED_QUERY_POOL_VK:
1220 wined3d_query_pool_vk_mark_free(context_vk, o->u.queries.pool_vk, o->u.queries.start, o->u.queries.count);
1221 TRACE("Freed query range %u+%u in pool %p.\n", o->u.queries.start, o->u.queries.count, o->u.queries.pool_vk);
1222 break;
1224 case WINED3D_RETIRED_EVENT_VK:
1225 VK_CALL(vkDestroyEvent(device_vk->vk_device, o->u.vk_event, NULL));
1226 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(o->u.vk_event));
1227 break;
1229 case WINED3D_RETIRED_PIPELINE_VK:
1230 VK_CALL(vkDestroyPipeline(device_vk->vk_device, o->u.vk_pipeline, NULL));
1231 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(o->u.vk_pipeline));
1232 break;
1234 default:
1235 ERR("Unhandled object type %#x.\n", o->type);
1236 break;
1239 if (i == retired->count)
1241 --retired->count;
1242 continue;
1245 o->type = WINED3D_RETIRED_FREE_VK;
1246 o->u.next = retired->free;
1247 retired->free = o;
1249 if (vk_fence && VK_CALL(vkGetFenceStatus(device_vk->vk_device, vk_fence)) != VK_NOT_READY)
1250 break;
1254 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
1256 struct wined3d_context_vk *context_vk = ctx;
1257 struct wined3d_bo_slab_vk *slab, *next;
1259 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
1260 while (slab)
1262 next = slab->next;
1263 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
1264 heap_free(slab);
1265 slab = next;
1269 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
1271 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
1272 struct wined3d_graphics_pipeline_vk, entry);
1273 struct wined3d_context_vk *context_vk = ctx;
1274 const struct wined3d_vk_info *vk_info;
1275 struct wined3d_device_vk *device_vk;
1277 vk_info = context_vk->vk_info;
1278 device_vk = wined3d_device_vk(context_vk->c.device);
1280 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
1281 heap_free(pipeline_vk);
1284 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
1286 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
1287 struct wined3d_pipeline_layout_vk, entry);
1288 struct wined3d_context_vk *context_vk = ctx;
1289 const struct wined3d_vk_info *vk_info;
1290 struct wined3d_device_vk *device_vk;
1292 vk_info = context_vk->vk_info;
1293 device_vk = wined3d_device_vk(context_vk->c.device);
1295 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
1296 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
1297 heap_free(layout->key.bindings);
1298 heap_free(layout);
1301 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
1302 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1304 struct wined3d_render_pass_attachment_vk *a;
1305 struct wined3d_rendertarget_view *view;
1306 unsigned int i;
1307 DWORD location;
1309 memset(key, 0, sizeof(*key));
1311 for (i = 0; i < rt_count; ++i)
1313 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1314 continue;
1316 a = &key->rt[i];
1317 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1318 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1319 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1320 location = wined3d_rendertarget_view_get_locations(view);
1322 if (clear_flags & WINED3DCLEAR_TARGET)
1323 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1324 else if (location & WINED3D_LOCATION_DISCARDED)
1325 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1326 else if (location & WINED3D_LOCATION_CLEARED)
1327 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1329 key->rt_mask |= 1u << i;
1332 if (depth_stencil && (view = fb->depth_stencil))
1334 a = &key->ds;
1335 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1336 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1337 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1338 location = wined3d_rendertarget_view_get_locations(view);
1339 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1341 if (clear_flags & WINED3DCLEAR_STENCIL)
1342 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S;
1343 if (clear_flags & WINED3DCLEAR_ZBUFFER)
1344 a->flags |= WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1346 if (!a->flags && (location & WINED3D_LOCATION_DISCARDED))
1347 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1348 else if (location & WINED3D_LOCATION_CLEARED)
1349 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S | WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1353 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1354 struct wined3d_context_vk *context_vk)
1356 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1357 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1359 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1362 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1363 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1365 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1366 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1367 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1368 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1369 const struct wined3d_render_pass_attachment_vk *a;
1370 VkAttachmentReference ds_attachment_reference;
1371 VkAttachmentReference *ds_reference = NULL;
1372 unsigned int attachment_count, rt_count, i;
1373 VkAttachmentDescription *attachment;
1374 VkSubpassDescription sub_pass_desc;
1375 VkRenderPassCreateInfo pass_desc;
1376 uint32_t mask;
1377 VkResult vr;
1379 rt_count = 0;
1380 attachment_count = 0;
1381 mask = key->rt_mask & wined3d_mask_from_size(WINED3D_MAX_RENDER_TARGETS);
1382 while (mask)
1384 i = wined3d_bit_scan(&mask);
1385 a = &key->rt[i];
1387 attachment = &attachments[attachment_count];
1388 attachment->flags = 0;
1389 attachment->format = a->vk_format;
1390 attachment->samples = a->vk_samples;
1392 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1393 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1394 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C)
1395 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1396 else
1397 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1399 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1400 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1401 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1402 attachment->initialLayout = a->vk_layout;
1403 attachment->finalLayout = a->vk_layout;
1405 attachment_references[i].attachment = attachment_count;
1406 attachment_references[i].layout = a->vk_layout;
1408 ++attachment_count;
1409 rt_count = i + 1;
1412 mask = ~key->rt_mask & wined3d_mask_from_size(rt_count);
1413 while (mask)
1415 i = wined3d_bit_scan(&mask);
1416 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1417 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1420 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1422 a = &key->ds;
1424 attachment = &attachments[attachment_count];
1425 attachment->flags = 0;
1426 attachment->format = a->vk_format;
1427 attachment->samples = a->vk_samples;
1429 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1430 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1431 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z)
1432 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1433 else
1434 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1436 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1437 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1438 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S)
1439 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1440 else
1441 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1443 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1444 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1445 attachment->initialLayout = a->vk_layout;
1446 attachment->finalLayout = a->vk_layout;
1448 ds_reference = &ds_attachment_reference;
1449 ds_reference->attachment = attachment_count;
1450 ds_reference->layout = a->vk_layout;
1452 ++attachment_count;
1455 sub_pass_desc.flags = 0;
1456 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1457 sub_pass_desc.inputAttachmentCount = 0;
1458 sub_pass_desc.pInputAttachments = NULL;
1459 sub_pass_desc.colorAttachmentCount = rt_count;
1460 sub_pass_desc.pColorAttachments = attachment_references;
1461 sub_pass_desc.pResolveAttachments = NULL;
1462 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1463 sub_pass_desc.preserveAttachmentCount = 0;
1464 sub_pass_desc.pPreserveAttachments = NULL;
1466 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1467 pass_desc.pNext = NULL;
1468 pass_desc.flags = 0;
1469 pass_desc.attachmentCount = attachment_count;
1470 pass_desc.pAttachments = attachments;
1471 pass_desc.subpassCount = 1;
1472 pass_desc.pSubpasses = &sub_pass_desc;
1473 pass_desc.dependencyCount = 0;
1474 pass_desc.pDependencies = NULL;
1476 pass->key = *key;
1477 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1478 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1480 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1481 return false;
1484 return true;
1487 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1488 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1490 struct wined3d_render_pass_key_vk key;
1491 struct wined3d_render_pass_vk *pass;
1492 struct wine_rb_entry *entry;
1494 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1495 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1496 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1498 if (!(pass = heap_alloc(sizeof(*pass))))
1499 return VK_NULL_HANDLE;
1501 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1503 heap_free(pass);
1504 return VK_NULL_HANDLE;
1507 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1509 ERR("Failed to insert render pass.\n");
1510 wined3d_render_pass_vk_cleanup(pass, context_vk);
1511 heap_free(pass);
1512 return VK_NULL_HANDLE;
1515 return pass->vk_render_pass;
1518 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1520 VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1521 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1522 struct wined3d_query_vk *query_vk;
1524 if (context_vk->vk_render_pass)
1526 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1527 wined3d_query_vk_suspend(query_vk, context_vk);
1529 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1530 context_vk->vk_render_pass = VK_NULL_HANDLE;
1531 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1532 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1534 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1536 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1538 ERR("Failed to allocate new query.\n");
1539 break;
1544 if (context_vk->vk_framebuffer)
1546 wined3d_context_vk_destroy_vk_framebuffer(context_vk,
1547 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1548 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1552 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1554 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1555 struct wined3d_render_pass_vk, entry);
1557 wined3d_render_pass_vk_cleanup(pass, ctx);
1558 heap_free(pass);
1561 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1563 heap_free(writes->writes);
1566 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1568 struct wined3d_query_pool_vk *pool_vk, *entry;
1570 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1572 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1573 heap_free(pool_vk);
1577 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1578 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1580 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1581 struct wined3d_query_pool_vk *pool_vk, *entry;
1582 struct wined3d_device_vk *device_vk;
1583 struct list *free_pools;
1584 VkResult vr;
1585 size_t idx;
1587 switch (type)
1589 case WINED3D_QUERY_TYPE_OCCLUSION:
1590 free_pools = &context_vk->free_occlusion_query_pools;
1591 break;
1593 case WINED3D_QUERY_TYPE_TIMESTAMP:
1594 free_pools = &context_vk->free_timestamp_query_pools;
1595 break;
1597 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1598 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1599 break;
1601 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1602 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1603 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1604 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1605 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1606 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1607 break;
1609 default:
1610 FIXME("Unhandled query type %#x.\n", type);
1611 return false;
1614 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1616 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1617 goto done;
1618 list_remove(&pool_vk->entry);
1619 list_init(&pool_vk->entry);
1622 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1623 return false;
1624 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1626 heap_free(pool_vk);
1627 return false;
1630 device_vk = wined3d_device_vk(context_vk->c.device);
1632 if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET])
1634 VK_CALL(vkResetQueryPoolEXT(device_vk->vk_device,
1635 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1637 else
1639 VkEventCreateInfo event_create_info;
1641 wined3d_context_vk_end_current_render_pass(context_vk);
1642 VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
1643 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1645 event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
1646 event_create_info.pNext = NULL;
1647 event_create_info.flags = 0;
1649 /* We probably shouldn't call vkGetQueryPoolResults() without synchronizing with vkCmdResetQueryPool()
1650 * even if the query pool is freshly allocated. wined3d_query_vk_accumulate_data() will check this event
1651 * before returning results. */
1652 vr = VK_CALL(vkCreateEvent(device_vk->vk_device, &event_create_info, NULL, &pool_vk->vk_event));
1653 if (vr == VK_SUCCESS)
1655 /* At which stage vkCmdResetQueryPool() executes? */
1656 VK_CALL(vkCmdSetEvent(wined3d_context_vk_get_command_buffer(context_vk), pool_vk->vk_event,
1657 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
1659 else
1661 ERR("Failed to create event, vr %s.\n", wined3d_debug_vkresult(vr));
1665 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1667 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1668 heap_free(pool_vk);
1669 return false;
1672 done:
1673 pool_idx->pool_vk = pool_vk;
1674 pool_idx->idx = idx;
1676 return true;
1679 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1681 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1682 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1683 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1684 unsigned int i;
1686 if (buffer->vk_command_buffer)
1688 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1689 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1690 buffer->vk_command_buffer = VK_NULL_HANDLE;
1693 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1694 context_vk->completed_command_buffer_id = buffer->id;
1696 heap_free(context_vk->compute.bindings.bindings);
1697 heap_free(context_vk->graphics.bindings.bindings);
1698 for (i = 0; i < context_vk->vk_descriptor_pool_count; ++i)
1699 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pools[i], NULL));
1700 heap_free(context_vk->vk_descriptor_pools);
1701 if (context_vk->vk_framebuffer)
1702 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1703 if (context_vk->vk_so_counter_bo.vk_buffer)
1704 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1705 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1706 /* Destroy the command pool after cleaning up resources. In particular,
1707 * this needs to happen after all command buffers are freed, because
1708 * vkFreeCommandBuffers() requires a valid pool handle. */
1709 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1710 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1711 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1712 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1713 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1714 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1715 heap_free(context_vk->submitted.buffers);
1716 heap_free(context_vk->retired.objects);
1718 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1719 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1720 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1721 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1723 wined3d_context_cleanup(&context_vk->c);
1726 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1728 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1729 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1730 VkCommandBufferAllocateInfo command_buffer_info;
1731 struct wined3d_command_buffer_vk *buffer;
1732 VkCommandBufferBeginInfo begin_info;
1733 struct wined3d_query_vk *query_vk;
1734 VkResult vr;
1736 TRACE("context_vk %p.\n", context_vk);
1738 buffer = &context_vk->current_command_buffer;
1739 if (buffer->vk_command_buffer)
1741 if (context_vk->retired_bo_size > WINED3D_RETIRED_BO_SIZE_THRESHOLD)
1742 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1743 else
1745 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1746 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1747 return buffer->vk_command_buffer;
1751 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1752 command_buffer_info.pNext = NULL;
1753 command_buffer_info.commandPool = context_vk->vk_command_pool;
1754 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1755 command_buffer_info.commandBufferCount = 1;
1756 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1757 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1759 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1760 return VK_NULL_HANDLE;
1763 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1764 begin_info.pNext = NULL;
1765 begin_info.flags = 0;
1766 begin_info.pInheritanceInfo = NULL;
1767 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1769 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1770 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1771 1, &buffer->vk_command_buffer));
1772 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1775 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1777 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1779 ERR("Failed to allocate new query.\n");
1780 break;
1783 wined3d_query_vk_resume(query_vk, context_vk);
1786 TRACE("Created new command buffer %p with id 0x%s.\n",
1787 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1789 return buffer->vk_command_buffer;
1792 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1793 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1794 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1796 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1797 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1798 struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
1799 struct wined3d_command_buffer_vk *buffer;
1800 struct wined3d_query_vk *query_vk;
1801 VkFenceCreateInfo fence_desc;
1802 VkSubmitInfo submit_info;
1803 VkResult vr;
1805 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1806 "signal_semaphore_count %u, signal_semaphores %p.\n",
1807 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1808 signal_semaphore_count, signal_semaphores);
1810 buffer = &context_vk->current_command_buffer;
1811 if (!buffer->vk_command_buffer)
1812 return;
1814 TRACE("Submitting command buffer %p with id 0x%s.\n",
1815 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1817 wined3d_context_vk_end_current_render_pass(context_vk);
1819 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
1820 struct wined3d_query_pool_vk, completed_entry)
1822 list_remove(&pool_vk->completed_entry);
1823 list_init(&pool_vk->completed_entry);
1825 wined3d_context_vk_reset_completed_queries(context_vk, pool_vk, buffer);
1828 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1829 wined3d_query_vk_suspend(query_vk, context_vk);
1831 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1832 context_vk->update_compute_pipeline = 1;
1833 context_vk->update_stream_output = 1;
1834 context_vk->c.update_shader_resource_bindings = 1;
1835 context_vk->c.update_compute_shader_resource_bindings = 1;
1836 context_vk->c.update_unordered_access_view_bindings = 1;
1837 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1838 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1839 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1840 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1841 context_invalidate_state(&context_vk->c, STATE_STENCIL_REF);
1843 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1845 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1846 fence_desc.pNext = NULL;
1847 fence_desc.flags = 0;
1848 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1849 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1851 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1852 submit_info.pNext = NULL;
1853 submit_info.waitSemaphoreCount = wait_semaphore_count;
1854 submit_info.pWaitSemaphores = wait_semaphores;
1855 submit_info.pWaitDstStageMask = wait_stages;
1856 submit_info.commandBufferCount = 1;
1857 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1858 submit_info.signalSemaphoreCount = signal_semaphore_count;
1859 submit_info.pSignalSemaphores = signal_semaphores;
1861 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1862 ERR("Failed to submit command buffer %p, vr %s.\n",
1863 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1865 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1866 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1867 ERR("Failed to grow submitted command buffer array.\n");
1869 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1871 buffer->vk_command_buffer = VK_NULL_HANDLE;
1872 /* We don't expect this to ever happen, but handle it anyway. */
1873 if (!++buffer->id)
1875 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1876 context_vk->completed_command_buffer_id = 0;
1877 buffer->id = 1;
1879 context_vk->retired_bo_size = 0;
1880 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1883 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1885 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1886 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1887 VkFence vk_fence;
1888 SIZE_T i;
1890 if (id <= context_vk->completed_command_buffer_id
1891 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1892 return;
1894 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1896 if (context_vk->submitted.buffers[i].id != id)
1897 continue;
1899 vk_fence = context_vk->submitted.buffers[i].vk_fence;
1900 wined3d_context_vk_cleanup_resources(context_vk, vk_fence);
1901 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1903 if (context_vk->submitted.buffers[i].id != id)
1904 continue;
1906 VK_CALL(vkWaitForFences(device_vk->vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX));
1907 wined3d_context_vk_remove_command_buffer(context_vk, i);
1908 return;
1912 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1915 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1916 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1917 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1918 VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range)
1920 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1921 VkImageMemoryBarrier barrier;
1923 wined3d_context_vk_end_current_render_pass(context_vk);
1925 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1926 barrier.pNext = NULL;
1927 barrier.srcAccessMask = src_access_mask;
1928 barrier.dstAccessMask = dst_access_mask;
1929 barrier.oldLayout = old_layout;
1930 barrier.newLayout = new_layout;
1931 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1932 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1933 barrier.image = image;
1934 barrier.subresourceRange = *range;
1936 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1939 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1941 const struct wined3d_render_pass_key_vk *k = key;
1942 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1943 const struct wined3d_render_pass_vk, entry);
1945 return memcmp(k, &pass->key, sizeof(*k));
1948 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1950 const struct wined3d_pipeline_layout_key_vk *a = key;
1951 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1952 const struct wined3d_pipeline_layout_vk, entry)->key;
1953 int ret;
1955 if ((ret = wined3d_uint32_compare(a->binding_count, b->binding_count)))
1956 return ret;
1957 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1960 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1962 const struct wined3d_graphics_pipeline_key_vk *a = key;
1963 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1964 const struct wined3d_graphics_pipeline_vk, entry)->key;
1965 unsigned int i;
1966 int ret;
1968 if ((ret = wined3d_uint32_compare(a->pipeline_desc.stageCount, b->pipeline_desc.stageCount)))
1969 return ret;
1970 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1972 if ((ret = wined3d_uint64_compare(a->stages[i].module, b->stages[i].module)))
1973 return ret;
1976 if ((ret = wined3d_uint32_compare(a->divisor_desc.vertexBindingDivisorCount,
1977 b->divisor_desc.vertexBindingDivisorCount)))
1978 return ret;
1979 if ((ret = memcmp(a->divisors, b->divisors,
1980 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1981 return ret;
1983 if ((ret = wined3d_uint32_compare(a->input_desc.vertexAttributeDescriptionCount,
1984 b->input_desc.vertexAttributeDescriptionCount)))
1985 return ret;
1986 if ((ret = memcmp(a->attributes, b->attributes,
1987 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1988 return ret;
1989 if ((ret = wined3d_uint32_compare(a->input_desc.vertexBindingDescriptionCount,
1990 b->input_desc.vertexBindingDescriptionCount)))
1991 return ret;
1992 if ((ret = memcmp(a->bindings, b->bindings,
1993 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1994 return ret;
1996 if ((ret = wined3d_uint32_compare(a->ia_desc.topology, b->ia_desc.topology)))
1997 return ret;
1998 if ((ret = wined3d_uint32_compare(a->ia_desc.primitiveRestartEnable, b->ia_desc.primitiveRestartEnable)))
1999 return ret;
2001 if ((ret = wined3d_uint32_compare(a->ts_desc.patchControlPoints, b->ts_desc.patchControlPoints)))
2002 return ret;
2004 if ((ret = memcmp(a->viewports, b->viewports, sizeof(a->viewports))))
2005 return ret;
2006 if ((ret = memcmp(a->scissors, b->scissors, sizeof(a->scissors))))
2007 return ret;
2009 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
2010 return ret;
2012 if ((ret = wined3d_uint32_compare(a->ms_desc.rasterizationSamples, b->ms_desc.rasterizationSamples)))
2013 return ret;
2014 if ((ret = wined3d_uint32_compare(a->ms_desc.alphaToCoverageEnable, b->ms_desc.alphaToCoverageEnable)))
2015 return ret;
2016 if ((ret = wined3d_uint32_compare(a->sample_mask, b->sample_mask)))
2017 return ret;
2019 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
2020 return ret;
2022 if ((ret = wined3d_uint32_compare(a->blend_desc.attachmentCount, b->blend_desc.attachmentCount)))
2023 return ret;
2024 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
2025 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
2026 return ret;
2028 if ((ret = wined3d_uint64_compare(a->pipeline_desc.layout, b->pipeline_desc.layout)))
2029 return ret;
2031 if ((ret = wined3d_uint64_compare(a->pipeline_desc.renderPass, b->pipeline_desc.renderPass)))
2032 return ret;
2034 return 0;
2037 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
2039 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
2040 const struct wined3d_bo_slab_vk_key *k = key;
2041 int ret;
2043 if ((ret = wined3d_uint32_compare(k->memory_type, slab->requested_memory_type)))
2044 return ret;
2045 if ((ret = wined3d_uint32_compare(k->usage, slab->bo.usage)))
2046 return ret;
2047 return wined3d_uint64_compare(k->size, slab->bo.size);
2050 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
2052 struct wined3d_graphics_pipeline_key_vk *key;
2053 VkPipelineShaderStageCreateInfo *stage;
2054 unsigned int i;
2056 static const VkDynamicState dynamic_states[] =
2058 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
2059 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
2062 key = &context_vk->graphics.pipeline_key_vk;
2063 memset(key, 0, sizeof(*key));
2065 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2067 stage = &key->stages[i];
2068 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
2069 stage->pName = "main";
2072 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
2073 key->input_desc.pVertexBindingDescriptions = key->bindings;
2074 key->input_desc.pVertexAttributeDescriptions = key->attributes;
2076 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
2077 key->divisor_desc.pVertexBindingDivisors = key->divisors;
2079 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
2081 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2083 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
2084 key->vp_desc.pViewports = key->viewports;
2085 key->vp_desc.pScissors = key->scissors;
2087 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
2088 key->rs_desc.lineWidth = 1.0f;
2090 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2091 key->ms_desc.pSampleMask = &key->sample_mask;
2093 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
2094 key->ds_desc.maxDepthBounds = 1.0f;
2096 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
2097 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
2098 key->blend_desc.pAttachments = key->blend_attachments;
2099 key->blend_desc.blendConstants[0] = 1.0f;
2100 key->blend_desc.blendConstants[1] = 1.0f;
2101 key->blend_desc.blendConstants[2] = 1.0f;
2102 key->blend_desc.blendConstants[3] = 1.0f;
2104 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2105 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
2106 key->dynamic_desc.pDynamicStates = dynamic_states;
2108 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2109 key->pipeline_desc.pStages = key->stages;
2110 key->pipeline_desc.pVertexInputState = &key->input_desc;
2111 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
2112 key->pipeline_desc.pTessellationState = &key->ts_desc;
2113 key->pipeline_desc.pViewportState = &key->vp_desc;
2114 key->pipeline_desc.pRasterizationState = &key->rs_desc;
2115 key->pipeline_desc.pMultisampleState = &key->ms_desc;
2116 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
2117 key->pipeline_desc.pColorBlendState = &key->blend_desc;
2118 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
2119 key->pipeline_desc.basePipelineIndex = -1;
2122 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
2123 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2125 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2126 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
2127 const struct wined3d_rasterizer_state_desc *r;
2128 float scale_bias;
2129 union
2131 uint32_t u32;
2132 float f32;
2133 } const_bias;
2135 if (!state->rasterizer_state)
2137 desc->depthClampEnable = VK_FALSE;
2138 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2139 desc->cullMode = VK_CULL_MODE_BACK_BIT;
2140 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
2141 desc->depthBiasEnable = VK_FALSE;
2142 desc->depthBiasConstantFactor = 0.0f;
2143 desc->depthBiasClamp = 0.0f;
2144 desc->depthBiasSlopeFactor = 0.0f;
2146 return;
2149 r = &state->rasterizer_state->desc;
2150 desc->depthClampEnable = !r->depth_clip;
2151 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2152 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
2153 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
2155 scale_bias = r->scale_bias;
2156 const_bias.f32 = r->depth_bias;
2157 if (!scale_bias && !const_bias.f32)
2159 desc->depthBiasEnable = VK_FALSE;
2160 desc->depthBiasConstantFactor = 0.0f;
2161 desc->depthBiasClamp = 0.0f;
2162 desc->depthBiasSlopeFactor = 0.0f;
2164 return;
2167 desc->depthBiasEnable = VK_TRUE;
2168 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
2170 const struct wined3d_rendertarget_view *dsv;
2172 if ((dsv = state->fb.depth_stencil))
2174 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
2175 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
2177 else
2179 desc->depthBiasConstantFactor = 0.0f;
2180 desc->depthBiasSlopeFactor = 0.0f;
2183 else
2185 desc->depthBiasConstantFactor = const_bias.f32;
2186 desc->depthBiasSlopeFactor = scale_bias;
2188 desc->depthBiasClamp = r->depth_bias_clamp;
2191 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
2192 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2194 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
2195 const struct wined3d_blend_state_desc *b;
2196 unsigned int i;
2198 desc->attachmentCount = context_vk->rt_count;
2200 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
2201 if (!state->blend_state)
2203 for (i = 0; i < context_vk->rt_count; ++i)
2205 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
2206 | VK_COLOR_COMPONENT_G_BIT
2207 | VK_COLOR_COMPONENT_B_BIT
2208 | VK_COLOR_COMPONENT_A_BIT;
2211 return;
2214 b = &state->blend_state->desc;
2215 for (i = 0; i < context_vk->rt_count; ++i)
2217 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2218 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2219 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2220 enum wined3d_blend src_blend, dst_blend;
2221 const struct wined3d_format *rt_format;
2223 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2224 if (!rt->enable)
2225 continue;
2227 if (rtv)
2228 rt_format = rtv->format;
2229 else
2230 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2231 a->blendEnable = VK_TRUE;
2233 src_blend = rt->src;
2234 dst_blend = rt->dst;
2235 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2237 src_blend = WINED3D_BLEND_SRCALPHA;
2238 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2240 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2242 src_blend = WINED3D_BLEND_INVSRCALPHA;
2243 dst_blend = WINED3D_BLEND_SRCALPHA;
2245 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2246 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2247 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2249 src_blend = rt->src_alpha;
2250 dst_blend = rt->dst_alpha;
2251 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2252 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2253 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2257 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2259 switch (component_type)
2261 case WINED3D_TYPE_UINT:
2262 return VK_FORMAT_R32G32B32A32_UINT;
2263 case WINED3D_TYPE_INT:
2264 return VK_FORMAT_R32G32B32A32_SINT;
2265 case WINED3D_TYPE_UNKNOWN:
2266 case WINED3D_TYPE_FLOAT:
2267 return VK_FORMAT_R32G32B32A32_SFLOAT;
2269 return VK_FORMAT_UNDEFINED;
2272 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2273 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2275 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2276 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2277 struct wined3d_graphics_pipeline_key_vk *key;
2278 VkPipelineShaderStageCreateInfo *stage;
2279 struct wined3d_stream_info stream_info;
2280 struct wined3d_shader *vertex_shader;
2281 VkPrimitiveTopology vk_topology;
2282 VkShaderModule module;
2283 bool update = false;
2284 uint32_t mask;
2286 *null_buffer_binding = ~0u;
2287 key = &context_vk->graphics.pipeline_key_vk;
2289 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2291 stage_count = 0;
2292 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2294 if (!(module = context_vk->graphics.vk_modules[i]))
2295 continue;
2297 stage = &key->stages[stage_count++];
2298 stage->stage = vk_shader_stage_from_wined3d(i);
2299 stage->module = module;
2302 key->pipeline_desc.stageCount = stage_count;
2304 update = true;
2307 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2308 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2309 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2311 VkVertexInputAttributeDescription *a;
2312 VkVertexInputBindingDescription *b;
2314 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2315 divisor_count = 0;
2316 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2318 VkVertexInputBindingDivisorDescriptionEXT *d;
2319 struct wined3d_stream_info_element *e;
2320 uint32_t binding;
2322 if (!(stream_info.use_map & (1u << i)))
2323 continue;
2325 a = &key->attributes[attribute_count++];
2326 e = &stream_info.elements[i];
2327 binding = e->stream_idx;
2329 a->location = i;
2330 a->binding = binding;
2331 a->format = wined3d_format_vk(e->format)->vk_format;
2332 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2334 if (mask & (1u << binding))
2335 continue;
2336 mask |= 1u << binding;
2338 b = &key->bindings[binding_count++];
2339 b->binding = binding;
2340 b->stride = e->stride;
2341 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2343 if (e->instanced)
2345 d = &key->divisors[divisor_count++];
2346 d->binding = binding;
2347 d->divisor = e->divisor;
2351 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2352 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2354 struct wined3d_shader_signature_element *element;
2355 struct wined3d_shader_signature *signature;
2356 uint32_t null_binding, location;
2358 if (!wined3d_get_unused_stream_index(state, &null_binding))
2360 ERR("No streams left for a null buffer binding.\n");
2362 else
2364 signature = &vertex_shader->input_signature;
2365 for (i = 0; i < signature->element_count; ++i)
2367 element = &signature->elements[i];
2368 location = element->register_idx;
2370 if (!(mask & (1u << location)) || element->sysval_semantic)
2371 continue;
2372 mask &= ~(1u << location);
2374 a = &key->attributes[attribute_count++];
2375 a->location = location;
2376 a->binding = null_binding;
2377 a->format = vk_format_from_component_type(element->component_type);
2378 a->offset = 0;
2381 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2383 b = &key->bindings[binding_count++];
2384 *null_buffer_binding = b->binding = null_binding;
2385 b->stride = 0;
2386 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2391 key->input_desc.pNext = NULL;
2392 key->input_desc.vertexBindingDescriptionCount = binding_count;
2393 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2395 if (divisor_count)
2397 key->input_desc.pNext = &key->divisor_desc;
2398 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2401 update = true;
2404 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2405 if (key->ia_desc.topology != vk_topology)
2407 key->ia_desc.topology = vk_topology;
2408 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2409 && !wined3d_primitive_type_is_list(state->primitive_type);
2411 update = true;
2414 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2416 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2418 update = true;
2421 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2422 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2423 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2425 key->vp_desc.viewportCount = (context_vk->vk_info->multiple_viewports ? WINED3D_MAX_VIEWPORTS : 1);
2426 key->vp_desc.scissorCount = key->vp_desc.viewportCount;
2428 for (i = 0; i < key->vp_desc.viewportCount; ++i)
2430 const struct wined3d_viewport *src_viewport = &state->viewports[i];
2431 VkViewport *viewport = &key->viewports[i];
2432 VkRect2D *scissor = &key->scissors[i];
2434 if (i >= state->viewport_count)
2436 viewport->x = 0.0f;
2437 viewport->y = 0.0f;
2438 viewport->width = 1.0f;
2439 viewport->height = 1.0f;
2440 viewport->minDepth = 0.0f;
2441 viewport->maxDepth = 0.0f;
2443 memset(scissor, 0, sizeof(*scissor));
2444 continue;
2447 viewport->x = src_viewport->x;
2448 viewport->y = src_viewport->y;
2449 viewport->width = src_viewport->width;
2450 viewport->height = src_viewport->height;
2451 viewport->minDepth = src_viewport->min_z;
2452 viewport->maxDepth = src_viewport->max_z;
2454 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2456 const RECT *r = &state->scissor_rects[i];
2458 if (i >= state->scissor_rect_count)
2460 memset(scissor, 0, sizeof(*scissor));
2461 continue;
2464 scissor->offset.x = r->left;
2465 scissor->offset.y = r->top;
2466 scissor->extent.width = r->right - r->left;
2467 scissor->extent.height = r->bottom - r->top;
2469 else
2471 scissor->offset.x = viewport->x;
2472 scissor->offset.y = viewport->y;
2473 scissor->extent.width = viewport->width;
2474 scissor->extent.height = viewport->height;
2476 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2477 if (scissor->offset.x < 0)
2478 scissor->offset.x = 0;
2479 if (scissor->offset.y < 0)
2480 scissor->offset.y = 0;
2481 viewport->y += viewport->height;
2482 viewport->height = -viewport->height;
2485 update = true;
2488 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2489 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2491 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2493 update = true;
2496 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2497 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2499 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2500 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2501 key->sample_mask = state->sample_mask;
2503 update = true;
2506 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2507 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2509 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2511 if (d)
2513 key->ds_desc.depthTestEnable = d->desc.depth;
2514 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2515 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2516 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2517 if (key->ds_desc.stencilTestEnable)
2519 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2520 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2521 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2522 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2523 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2524 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2526 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2527 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2528 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2529 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2530 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2531 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2533 else
2535 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2536 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2539 else
2541 key->ds_desc.depthTestEnable = VK_TRUE;
2542 key->ds_desc.depthWriteEnable = VK_TRUE;
2543 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2544 key->ds_desc.stencilTestEnable = VK_FALSE;
2547 update = true;
2550 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2551 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2553 wined3d_context_vk_update_blend_state(context_vk, state, key);
2555 update = true;
2558 if (key->pipeline_desc.layout != vk_pipeline_layout)
2560 key->pipeline_desc.layout = vk_pipeline_layout;
2562 update = true;
2565 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2567 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2569 update = true;
2572 return update;
2575 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2576 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2578 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2579 VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
2580 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2581 unsigned int fb_width, fb_height, fb_layer_count;
2582 struct wined3d_rendertarget_view_vk *rtv_vk;
2583 struct wined3d_rendertarget_view *view;
2584 const VkPhysicalDeviceLimits *limits;
2585 struct wined3d_query_vk *query_vk;
2586 VkRenderPassBeginInfo begin_info;
2587 unsigned int attachment_count, i;
2588 struct wined3d_texture *texture;
2589 VkFramebufferCreateInfo fb_desc;
2590 VkResult vr;
2592 if (context_vk->vk_render_pass)
2593 return true;
2595 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2596 fb_width = limits->maxFramebufferWidth;
2597 fb_height = limits->maxFramebufferHeight;
2598 fb_layer_count = limits->maxFramebufferLayers;
2599 attachment_count = 0;
2601 context_vk->rt_count = 0;
2602 begin_info.clearValueCount = 0;
2603 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2605 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2606 continue;
2608 rtv_vk = wined3d_rendertarget_view_vk(view);
2610 if (rtv_vk->v.resource->bind_count)
2612 struct wined3d_texture_vk *texture_vk;
2613 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource));
2614 wined3d_texture_vk_make_generic(texture_vk, context_vk);
2617 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2618 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2619 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2621 if (view->width < fb_width)
2622 fb_width = view->width;
2623 if (view->height < fb_height)
2624 fb_height = view->height;
2625 if (view->layer_count < fb_layer_count)
2626 fb_layer_count = view->layer_count;
2627 context_vk->rt_count = i + 1;
2629 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2631 VkClearColorValue *c = &clear_values[attachment_count].color;
2633 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2635 c->int32[0] = c->int32[1] = c->int32[2] = c->int32[3] = 0;
2637 else
2639 texture = texture_from_resource(view->resource);
2640 wined3d_format_colour_to_vk(view->format,
2641 &texture->sub_resources[view->sub_resource_idx].clear_value.colour, c);
2644 begin_info.clearValueCount = attachment_count + 1;
2646 ++attachment_count;
2649 if ((view = state->fb.depth_stencil))
2651 rtv_vk = wined3d_rendertarget_view_vk(view);
2653 if (rtv_vk->v.resource->bind_count)
2655 struct wined3d_texture_vk *texture_vk;
2656 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource));
2657 wined3d_texture_vk_make_generic(texture_vk, context_vk);
2660 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2661 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2662 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2664 if (view->width < fb_width)
2665 fb_width = view->width;
2666 if (view->height < fb_height)
2667 fb_height = view->height;
2668 if (view->layer_count < fb_layer_count)
2669 fb_layer_count = view->layer_count;
2671 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2673 VkClearDepthStencilValue *c = &clear_values[attachment_count].depthStencil;
2675 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2677 c->depth = 0.0f;
2678 c->stencil = 0;
2680 else
2682 texture = texture_from_resource(view->resource);
2683 c->depth = texture->sub_resources[view->sub_resource_idx].clear_value.depth;
2684 c->stencil = texture->sub_resources[view->sub_resource_idx].clear_value.stencil;
2686 begin_info.clearValueCount = attachment_count + 1;
2688 ++attachment_count;
2691 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2692 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2694 ERR("Failed to get render pass.\n");
2695 return false;
2698 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2699 fb_desc.pNext = NULL;
2700 fb_desc.flags = 0;
2701 fb_desc.renderPass = context_vk->vk_render_pass;
2702 fb_desc.attachmentCount = attachment_count;
2703 fb_desc.pAttachments = vk_views;
2704 fb_desc.width = fb_width;
2705 fb_desc.height = fb_height;
2706 fb_desc.layers = fb_layer_count;
2708 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2710 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2711 return false;
2714 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2715 begin_info.pNext = NULL;
2716 begin_info.renderPass = context_vk->vk_render_pass;
2717 begin_info.framebuffer = context_vk->vk_framebuffer;
2718 begin_info.renderArea.offset.x = 0;
2719 begin_info.renderArea.offset.y = 0;
2720 begin_info.renderArea.extent.width = fb_width;
2721 begin_info.renderArea.extent.height = fb_height;
2722 begin_info.pClearValues = clear_values;
2723 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2725 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2726 wined3d_query_vk_resume(query_vk, context_vk);
2727 return true;
2730 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2731 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2733 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2734 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2735 const struct wined3d_stream_state *stream;
2736 const VkDescriptorBufferInfo *buffer_info;
2737 struct wined3d_buffer_vk *buffer_vk;
2738 struct wined3d_buffer *buffer;
2739 unsigned int i, first, count;
2741 first = 0;
2742 count = 0;
2743 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2745 stream = &state->streams[i];
2747 if ((buffer = stream->buffer))
2749 buffer_vk = wined3d_buffer_vk(buffer);
2750 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2751 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2752 buffers[count] = buffer_info->buffer;
2753 offsets[count] = buffer_info->offset + stream->offset;
2754 ++count;
2755 continue;
2758 if (count)
2759 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2760 first = i + 1;
2761 count = 0;
2764 if (count)
2765 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2768 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2769 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2771 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2772 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2773 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2774 const struct wined3d_stream_output *stream;
2775 const VkDescriptorBufferInfo *buffer_info;
2776 struct wined3d_buffer_vk *buffer_vk;
2777 struct wined3d_buffer *buffer;
2778 unsigned int i, first, count;
2780 first = 0;
2781 count = 0;
2782 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2784 stream = &state->stream_output[i];
2786 if ((buffer = stream->buffer))
2788 buffer_vk = wined3d_buffer_vk(buffer);
2789 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2790 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2791 buffers[count] = buffer_info->buffer;
2792 if ((offsets[count] = stream->offset) == ~0u)
2794 FIXME("Appending to stream output buffers not implemented.\n");
2795 offsets[count] = 0;
2797 sizes[count] = buffer_info->range - offsets[count];
2798 offsets[count] += buffer_info->offset;
2799 ++count;
2800 continue;
2803 if (count)
2804 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2805 first = i + 1;
2806 count = 0;
2809 if (count)
2810 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2813 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2814 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2816 struct VkDescriptorPoolCreateInfo pool_desc;
2817 VkResult vr;
2819 static const VkDescriptorPoolSize pool_sizes[] =
2821 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2822 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2823 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2824 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2825 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2826 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2829 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2830 pool_desc.pNext = NULL;
2831 pool_desc.flags = 0;
2832 pool_desc.maxSets = 512;
2833 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2834 pool_desc.pPoolSizes = pool_sizes;
2836 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2837 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2839 return vr;
2842 VkDescriptorPool wined3d_context_vk_get_vk_descriptor_pool(struct wined3d_context_vk *context_vk)
2844 VkResult vr;
2846 if (context_vk->vk_descriptor_pool_count)
2847 return context_vk->vk_descriptor_pools[0];
2849 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
2850 1, sizeof(*context_vk->vk_descriptor_pools)))
2852 ERR("Failed to allocate array.\n");
2853 return VK_NULL_HANDLE;
2856 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(wined3d_device_vk(context_vk->c.device),
2857 context_vk->vk_info, context_vk->vk_descriptor_pools)))
2859 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2860 return VK_NULL_HANDLE;
2863 context_vk->vk_descriptor_pool_count = 1;
2864 return context_vk->vk_descriptor_pools[0];
2867 VkDescriptorSet wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2868 VkDescriptorSetLayout vk_set_layout)
2870 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2871 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2872 struct VkDescriptorSetAllocateInfo set_desc;
2873 VkDescriptorPool vk_descriptor_pool;
2874 VkDescriptorSet vk_descriptor_set;
2875 VkResult vr;
2877 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2878 return VK_NULL_HANDLE;
2880 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2881 set_desc.pNext = NULL;
2882 set_desc.descriptorPool = vk_descriptor_pool;
2883 set_desc.descriptorSetCount = 1;
2884 set_desc.pSetLayouts = &vk_set_layout;
2885 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2886 return vk_descriptor_set;
2888 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2890 wined3d_context_vk_reset_vk_descriptor_pool(context_vk,
2891 vk_descriptor_pool, context_vk->current_command_buffer.id);
2892 context_vk->vk_descriptor_pools[0] = context_vk->vk_descriptor_pools[--context_vk->vk_descriptor_pool_count];
2893 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2895 WARN("Failed to create descriptor pool.\n");
2896 return VK_NULL_HANDLE;
2899 set_desc.descriptorPool = vk_descriptor_pool;
2900 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2901 return vk_descriptor_set;
2904 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2906 return VK_NULL_HANDLE;
2909 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2910 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2911 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2912 const VkBufferView *buffer_view)
2914 SIZE_T write_count = writes->count;
2915 VkWriteDescriptorSet *write;
2917 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2918 write_count + 1, sizeof(*writes->writes)))
2919 return false;
2921 write = &writes->writes[write_count];
2922 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2923 write->pNext = NULL;
2924 write->dstSet = vk_descriptor_set;
2925 write->dstBinding = binding_idx;
2926 write->dstArrayElement = 0;
2927 write->descriptorCount = 1;
2928 write->descriptorType = type;
2929 write->pImageInfo = image_info;
2930 write->pBufferInfo = buffer_info;
2931 write->pTexelBufferView = buffer_view;
2933 ++writes->count;
2935 return true;
2938 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2939 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2940 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2942 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2944 switch (type)
2946 case WINED3D_SHADER_RESOURCE_BUFFER:
2947 if (data_type == WINED3D_DATA_FLOAT)
2948 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2949 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2950 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2951 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2953 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2954 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2955 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2957 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2958 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2959 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2961 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2962 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2963 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2965 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2966 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2967 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2969 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2970 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2971 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2973 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2974 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2975 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
2977 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2978 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2979 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2981 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2982 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2983 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2985 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
2986 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2987 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube_array, NULL);
2989 default:
2990 FIXME("Unhandled resource type %#x.\n", type);
2991 return false;
2995 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2996 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2997 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
2999 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
3000 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3001 struct wined3d_buffer_vk *buffer_vk;
3002 struct wined3d_buffer *buffer;
3004 if (!(buffer = cb_state->buffer))
3005 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3006 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
3008 buffer_vk = wined3d_buffer_vk(buffer);
3009 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
3010 buffer_info->offset += cb_state->offset;
3011 buffer_info->range = min(cb_state->size, buffer_info->range);
3012 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3013 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
3014 return false;
3015 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
3016 return true;
3019 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
3020 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3021 const struct wined3d_shader_resource_binding *binding)
3023 struct wined3d_shader_resource_view_vk *srv_vk;
3024 struct wined3d_shader_resource_view *srv;
3025 const VkDescriptorImageInfo *image_info;
3026 struct wined3d_resource *resource;
3027 struct wined3d_view_vk *view_vk;
3028 VkBufferView *buffer_view;
3029 VkDescriptorType type;
3031 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3032 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
3033 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
3035 resource = srv->resource;
3036 srv_vk = wined3d_shader_resource_view_vk(srv);
3037 view_vk = &srv_vk->view_vk;
3038 if (resource->type == WINED3D_RTYPE_BUFFER)
3040 image_info = NULL;
3041 buffer_view = &view_vk->u.vk_buffer_view;
3042 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
3044 else
3046 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3048 if (view_vk->u.vk_image_info.imageView)
3050 image_info = &view_vk->u.vk_image_info;
3051 if (image_info->imageLayout != texture_vk->layout)
3052 wined3d_shader_resource_view_vk_update_layout(srv_vk, texture_vk->layout);
3054 else
3055 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3056 buffer_view = NULL;
3057 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3060 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3061 binding->binding_idx, type, NULL, image_info, buffer_view))
3062 return false;
3063 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
3064 return true;
3067 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
3068 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3069 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3071 struct wined3d_unordered_access_view_vk *uav_vk;
3072 struct wined3d_unordered_access_view *uav;
3073 const VkDescriptorImageInfo *image_info;
3074 struct wined3d_resource *resource;
3075 struct wined3d_view_vk *view_vk;
3076 VkBufferView *buffer_view;
3077 VkDescriptorType type;
3079 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3081 FIXME("NULL unordered access views not implemented.\n");
3082 return false;
3084 resource = uav->resource;
3086 uav_vk = wined3d_unordered_access_view_vk(uav);
3087 view_vk = &uav_vk->view_vk;
3088 if (resource->type == WINED3D_RTYPE_BUFFER)
3090 image_info = NULL;
3091 buffer_view = &view_vk->u.vk_buffer_view;
3092 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
3094 else
3096 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3098 if (view_vk->u.vk_image_info.imageView)
3099 image_info = &view_vk->u.vk_image_info;
3100 else
3101 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3102 buffer_view = NULL;
3103 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3106 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3107 binding->binding_idx, type, NULL, image_info, buffer_view))
3108 return false;
3109 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
3110 return true;
3113 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
3114 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
3115 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3116 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3118 struct wined3d_unordered_access_view_vk *uav_vk;
3119 struct wined3d_unordered_access_view *uav;
3121 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3123 FIXME("NULL unordered access view counters not implemented.\n");
3124 return false;
3127 uav_vk = wined3d_unordered_access_view_vk(uav);
3128 if (!uav_vk->vk_counter_view)
3129 return false;
3131 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3132 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
3135 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
3136 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3137 const struct wined3d_shader_resource_binding *binding)
3139 struct wined3d_sampler *sampler;
3141 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3142 sampler = context_vk->c.device->null_sampler;
3143 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3144 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
3145 return false;
3146 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
3147 return true;
3150 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
3151 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3153 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3154 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
3155 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3156 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3157 const struct wined3d_shader_resource_binding *binding;
3158 struct wined3d_shader_resource_bindings *bindings;
3159 VkDescriptorSetLayout vk_set_layout;
3160 VkPipelineLayout vk_pipeline_layout;
3161 VkPipelineBindPoint vk_bind_point;
3162 VkDescriptorSet vk_descriptor_set;
3163 size_t i;
3165 switch (pipeline)
3167 case WINED3D_PIPELINE_GRAPHICS:
3168 bindings = &context_vk->graphics.bindings;
3169 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
3170 vk_set_layout = context_vk->graphics.vk_set_layout;
3171 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
3172 break;
3174 case WINED3D_PIPELINE_COMPUTE:
3175 bindings = &context_vk->compute.bindings;
3176 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
3177 vk_set_layout = context_vk->compute.vk_set_layout;
3178 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
3179 break;
3181 default:
3182 ERR("Invalid pipeline %#x.\n", pipeline);
3183 return false;
3186 if (!(vk_descriptor_set = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout)))
3188 WARN("Failed to create descriptor set.\n");
3189 return false;
3192 writes->count = 0;
3193 for (i = 0; i < bindings->count; ++i)
3195 binding = &bindings->bindings[i];
3197 switch (binding->shader_descriptor_type)
3199 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3200 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
3201 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
3202 return false;
3203 break;
3205 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3206 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
3207 context_vk, vk_descriptor_set, state, binding))
3208 return false;
3209 break;
3211 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3212 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
3213 context_vk, pipeline, vk_descriptor_set, state, binding))
3214 return false;
3215 break;
3217 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3218 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
3219 context_vk, pipeline, vk_descriptor_set, state, binding))
3220 return false;
3221 break;
3223 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3224 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
3225 context_vk, vk_descriptor_set, state, binding))
3226 return false;
3227 break;
3229 default:
3230 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3231 return false;
3235 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
3236 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
3237 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
3239 return true;
3242 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
3243 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
3244 VkDescriptorSetLayout *vk_set_layout)
3246 VkDescriptorSetLayoutCreateInfo layout_desc;
3247 VkResult vr;
3249 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3250 layout_desc.pNext = NULL;
3251 layout_desc.flags = 0;
3252 layout_desc.bindingCount = key->binding_count;
3253 layout_desc.pBindings = key->bindings;
3255 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
3256 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3258 return vr;
3261 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
3262 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
3264 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3265 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3266 struct wined3d_pipeline_layout_key_vk key;
3267 struct wined3d_pipeline_layout_vk *layout;
3268 VkPipelineLayoutCreateInfo layout_desc;
3269 struct wine_rb_entry *entry;
3270 VkResult vr;
3272 key.bindings = bindings;
3273 key.binding_count = binding_count;
3274 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
3275 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
3277 if (!(layout = heap_alloc(sizeof(*layout))))
3278 return NULL;
3280 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
3282 heap_free(layout);
3283 return NULL;
3285 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
3286 layout->key.binding_count = key.binding_count;
3288 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
3290 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3291 goto fail;
3294 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3295 layout_desc.pNext = NULL;
3296 layout_desc.flags = 0;
3297 layout_desc.setLayoutCount = 1;
3298 layout_desc.pSetLayouts = &layout->vk_set_layout;
3299 layout_desc.pushConstantRangeCount = 0;
3300 layout_desc.pPushConstantRanges = NULL;
3302 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
3303 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
3305 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
3306 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3307 goto fail;
3310 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
3312 ERR("Failed to insert pipeline layout.\n");
3313 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3314 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3315 goto fail;
3318 return layout;
3320 fail:
3321 heap_free(layout->key.bindings);
3322 heap_free(layout);
3323 return NULL;
3326 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3328 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3329 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3330 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3331 struct wined3d_graphics_pipeline_key_vk *key;
3332 struct wine_rb_entry *entry;
3333 VkResult vr;
3335 key = &context_vk->graphics.pipeline_key_vk;
3336 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3337 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3339 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3340 return VK_NULL_HANDLE;
3341 pipeline_vk->key = *key;
3343 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3344 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3346 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3347 heap_free(pipeline_vk);
3348 return VK_NULL_HANDLE;
3351 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3352 ERR("Failed to insert pipeline.\n");
3354 return pipeline_vk->vk_pipeline;
3357 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3358 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3360 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3361 const struct wined3d_shader_resource_bindings *bindings;
3362 const struct wined3d_shader_resource_binding *binding;
3363 struct wined3d_unordered_access_view_vk *uav_vk;
3364 struct wined3d_shader_resource_view_vk *srv_vk;
3365 struct wined3d_unordered_access_view *uav;
3366 struct wined3d_shader_resource_view *srv;
3367 struct wined3d_buffer_vk *buffer_vk;
3368 struct wined3d_sampler *sampler;
3369 struct wined3d_buffer *buffer;
3370 size_t i;
3372 switch (pipeline)
3374 case WINED3D_PIPELINE_GRAPHICS:
3375 bindings = &context_vk->graphics.bindings;
3376 break;
3378 case WINED3D_PIPELINE_COMPUTE:
3379 bindings = &context_vk->compute.bindings;
3380 break;
3382 default:
3383 ERR("Invalid pipeline %#x.\n", pipeline);
3384 return;
3387 writes->count = 0;
3388 for (i = 0; i < bindings->count; ++i)
3390 binding = &bindings->bindings[i];
3392 switch (binding->shader_descriptor_type)
3394 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3395 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3396 break;
3398 buffer_vk = wined3d_buffer_vk(buffer);
3399 wined3d_buffer_load(buffer, &context_vk->c, state);
3400 if (!buffer_vk->b.bo_user.valid)
3402 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3403 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3404 else
3405 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3407 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3408 break;
3410 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3411 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3412 break;
3414 srv_vk = wined3d_shader_resource_view_vk(srv);
3415 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3417 if (!srv_vk->view_vk.bo_user.valid)
3419 wined3d_shader_resource_view_vk_update_buffer(srv_vk, context_vk);
3420 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3421 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3422 else
3423 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3425 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3427 else
3429 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3431 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3432 break;
3434 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3435 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3436 break;
3438 uav_vk = wined3d_unordered_access_view_vk(uav);
3439 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3441 if (!uav_vk->view_vk.bo_user.valid)
3443 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3444 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3445 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3446 else
3447 context_invalidate_compute_state(&context_vk->c,
3448 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3450 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3451 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3453 else
3455 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3456 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3458 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3459 break;
3461 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3462 break;
3464 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3465 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3466 sampler = context_vk->c.device->null_sampler;
3467 break;
3469 default:
3470 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3471 break;
3476 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3477 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3479 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3480 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3481 const struct wined3d_blend_state *b = state->blend_state;
3482 bool dual_source_blend = b && b->dual_source;
3483 struct wined3d_rendertarget_view *dsv;
3484 struct wined3d_rendertarget_view *rtv;
3485 struct wined3d_buffer_vk *buffer_vk;
3486 VkSampleCountFlagBits sample_count;
3487 VkCommandBuffer vk_command_buffer;
3488 unsigned int i, invalidate_rt = 0;
3489 struct wined3d_buffer *buffer;
3490 uint32_t null_buffer_binding;
3491 bool invalidate_ds = false;
3493 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3494 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)
3495 || dual_source_blend != context_vk->c.last_was_dual_source_blend)
3497 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3498 context_vk->c.last_was_dual_source_blend = dual_source_blend;
3500 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3501 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3502 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3503 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3504 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3505 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3506 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3507 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3509 context_vk->sample_count = 0;
3510 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3512 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3513 continue;
3515 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3517 /* We handle clears at the beginning of the render pass, no need for an explicit clear
3518 * first. */
3519 if (wined3d_rendertarget_view_get_locations(rtv) & WINED3D_LOCATION_CLEARED)
3520 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3521 else
3522 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3523 invalidate_rt |= (1 << i);
3525 else
3527 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3530 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3531 if (!context_vk->sample_count)
3532 context_vk->sample_count = sample_count;
3533 else if (context_vk->sample_count != sample_count)
3534 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3537 if ((dsv = state->fb.depth_stencil))
3539 if (wined3d_state_uses_depth_buffer(state))
3541 if (wined3d_rendertarget_view_get_locations(dsv) & WINED3D_LOCATION_CLEARED)
3542 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3543 else
3544 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3546 else
3548 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3551 if (!state->depth_stencil_state || state->depth_stencil_state->writes_ds)
3552 invalidate_ds = true;
3554 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3555 if (!context_vk->sample_count)
3556 context_vk->sample_count = sample_count;
3557 else if (context_vk->sample_count != sample_count)
3558 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3561 if (!context_vk->sample_count)
3562 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3563 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3565 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3566 if (!context_vk->graphics.vk_pipeline_layout)
3568 ERR("No pipeline layout set.\n");
3569 return VK_NULL_HANDLE;
3571 context_vk->c.update_shader_resource_bindings = 1;
3572 context_vk->c.update_unordered_access_view_bindings = 1;
3575 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3577 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3579 if (!(buffer = state->streams[i].buffer))
3580 continue;
3582 buffer_vk = wined3d_buffer_vk(buffer);
3583 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3584 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3585 if (!buffer_vk->b.bo_user.valid)
3586 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3589 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3591 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3593 if (!(buffer = state->stream_output[i].buffer))
3594 continue;
3596 buffer_vk = wined3d_buffer_vk(buffer);
3597 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3598 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3599 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3600 if (!buffer_vk->b.bo_user.valid)
3601 context_vk->update_stream_output = 1;
3603 context_vk->c.transform_feedback_active = 1;
3606 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3608 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3609 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3610 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3611 if (!buffer_vk->b.bo_user.valid)
3612 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3615 if (indirect_vk)
3617 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3618 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3621 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3623 ERR("Failed to get command buffer.\n");
3624 return VK_NULL_HANDLE;
3627 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3628 wined3d_context_vk_end_current_render_pass(context_vk);
3629 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3631 ERR("Failed to begin render pass.\n");
3632 return VK_NULL_HANDLE;
3635 while (invalidate_rt)
3637 i = wined3d_bit_scan(&invalidate_rt);
3638 rtv = state->fb.render_targets[i];
3639 wined3d_rendertarget_view_validate_location(rtv, rtv->resource->draw_binding);
3640 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3643 if (invalidate_ds)
3645 wined3d_rendertarget_view_validate_location(dsv, dsv->resource->draw_binding);
3646 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3649 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3650 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3652 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3654 ERR("Failed to get graphics pipeline.\n");
3655 return VK_NULL_HANDLE;
3658 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3659 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3660 if (null_buffer_binding != ~0u)
3662 VkDeviceSize offset = 0;
3663 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3664 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3668 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3670 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3671 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3674 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3675 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3677 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3679 context_vk->update_stream_output = 1;
3680 context_vk->c.transform_feedback_paused = 0;
3682 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3684 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3685 context_vk->update_stream_output = 0;
3688 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3690 const VkDescriptorBufferInfo *buffer_info;
3691 VkIndexType idx_type;
3693 if (state->index_format == WINED3DFMT_R16_UINT)
3694 idx_type = VK_INDEX_TYPE_UINT16;
3695 else
3696 idx_type = VK_INDEX_TYPE_UINT32;
3697 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3698 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3699 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer_vk->b.buffer_object));
3700 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3701 buffer_info->offset + state->index_offset, idx_type));
3704 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3705 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3706 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3707 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3708 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3709 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3710 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3711 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3712 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3713 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3714 context_vk->c.update_shader_resource_bindings = 1;
3715 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3716 context_vk->c.update_unordered_access_view_bindings = 1;
3718 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3720 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3722 ERR("Failed to update shader descriptors.\n");
3723 return VK_NULL_HANDLE;
3726 context_vk->c.update_shader_resource_bindings = 0;
3727 context_vk->c.update_unordered_access_view_bindings = 0;
3730 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3731 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3733 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3734 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3736 return vk_command_buffer;
3739 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3740 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3742 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3743 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3744 VkCommandBuffer vk_command_buffer;
3746 wined3d_context_vk_end_current_render_pass(context_vk);
3748 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3749 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3751 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3753 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3754 if (!context_vk->compute.vk_pipeline)
3756 ERR("No compute pipeline set.\n");
3757 return VK_NULL_HANDLE;
3759 context_vk->c.update_compute_shader_resource_bindings = 1;
3760 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3761 context_vk->update_compute_pipeline = 1;
3764 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3766 if (indirect_vk)
3768 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3769 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3772 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3774 ERR("Failed to get command buffer.\n");
3775 return VK_NULL_HANDLE;
3778 if (context_vk->update_compute_pipeline)
3780 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3781 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3782 context_vk->update_compute_pipeline = 0;
3785 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3786 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3787 context_vk->c.update_compute_shader_resource_bindings = 1;
3788 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3789 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3791 if (context_vk->c.update_compute_shader_resource_bindings
3792 || context_vk->c.update_compute_unordered_access_view_bindings)
3794 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3796 ERR("Failed to update shader descriptors.\n");
3797 return VK_NULL_HANDLE;
3800 context_vk->c.update_compute_shader_resource_bindings = 0;
3801 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3804 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3805 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3807 return vk_command_buffer;
3810 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3812 VkCommandPoolCreateInfo command_pool_info;
3813 const struct wined3d_vk_info *vk_info;
3814 struct wined3d_adapter_vk *adapter_vk;
3815 struct wined3d_device_vk *device_vk;
3816 VkResult vr;
3818 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3820 memset(context_vk, 0, sizeof(*context_vk));
3821 wined3d_context_init(&context_vk->c, swapchain);
3822 device_vk = wined3d_device_vk(swapchain->device);
3823 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3824 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3826 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3827 command_pool_info.pNext = NULL;
3828 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3829 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3830 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3831 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3833 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3834 wined3d_context_cleanup(&context_vk->c);
3835 return E_FAIL;
3837 context_vk->current_command_buffer.id = 1;
3839 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3841 list_init(&context_vk->render_pass_queries);
3842 list_init(&context_vk->active_queries);
3843 list_init(&context_vk->completed_query_pools);
3844 list_init(&context_vk->free_occlusion_query_pools);
3845 list_init(&context_vk->free_timestamp_query_pools);
3846 list_init(&context_vk->free_pipeline_statistics_query_pools);
3847 list_init(&context_vk->free_stream_output_statistics_query_pools);
3849 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3850 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3851 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3852 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3854 return WINED3D_OK;