wineps: Handle EMR_INVERTRGN record in spool files.
[wine.git] / dlls / wined3d / context_vk.c
blob1acb8a8d20121b4ecabfda49dc6ddb16c02763b0
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 void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk)
249 wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
252 static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk)
254 wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
257 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
258 struct wined3d_context_vk *context_vk)
260 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
261 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
262 void *map_ptr;
263 VkResult vr;
265 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
266 wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
268 wined3d_allocator_chunk_vk_lock(chunk_vk);
270 if (!chunk_vk->c.map_ptr)
272 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device,
273 chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
275 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
276 wined3d_allocator_chunk_vk_unlock(chunk_vk);
277 return NULL;
280 adapter_adjust_mapped_memory(device_vk->d.adapter, WINED3D_ALLOCATOR_CHUNK_SIZE);
283 ++chunk_vk->c.map_count;
284 map_ptr = chunk_vk->c.map_ptr;
286 wined3d_allocator_chunk_vk_unlock(chunk_vk);
288 return map_ptr;
291 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
292 struct wined3d_context_vk *context_vk)
294 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
295 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
297 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
299 wined3d_allocator_chunk_vk_lock(chunk_vk);
301 if (--chunk_vk->c.map_count)
303 wined3d_allocator_chunk_vk_unlock(chunk_vk);
304 return;
307 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
308 chunk_vk->c.map_ptr = NULL;
310 wined3d_allocator_chunk_vk_unlock(chunk_vk);
312 adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE);
315 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
316 unsigned int pool, size_t size)
318 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
319 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
320 VkMemoryAllocateInfo allocate_info;
321 VkDeviceMemory vk_memory;
322 VkResult vr;
324 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
325 allocate_info.pNext = NULL;
326 allocate_info.allocationSize = size;
327 allocate_info.memoryTypeIndex = pool;
328 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
330 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
331 return VK_NULL_HANDLE;
334 return vk_memory;
337 static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
338 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
340 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
341 struct wined3d_allocator *allocator = &device_vk->allocator;
342 struct wined3d_allocator_block *block;
344 wined3d_device_vk_allocator_lock(device_vk);
346 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
348 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
349 wined3d_device_vk_allocator_unlock(device_vk);
350 return NULL;
353 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
355 wined3d_device_vk_allocator_unlock(device_vk);
356 *vk_memory = VK_NULL_HANDLE;
357 return NULL;
360 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
362 wined3d_device_vk_allocator_unlock(device_vk);
363 return block;
366 static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block)
368 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
370 assert(block->chunk->allocator == &device_vk->allocator);
371 wined3d_device_vk_allocator_lock(device_vk);
372 wined3d_allocator_block_free(block);
373 wined3d_device_vk_allocator_unlock(device_vk);
376 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
377 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
379 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
380 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
381 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
382 struct wined3d_bo_slab_vk_key key;
383 struct wined3d_bo_slab_vk *slab;
384 struct wine_rb_entry *entry;
385 size_t object_size, idx;
386 size_t alignment;
388 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
389 return false;
391 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
392 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
393 && limits->minTexelBufferOffsetAlignment > alignment)
394 alignment = limits->minTexelBufferOffsetAlignment;
395 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
396 alignment = limits->minUniformBufferOffsetAlignment;
397 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
398 alignment = limits->minStorageBufferOffsetAlignment;
400 object_size = (size + (alignment - 1)) & ~(alignment - 1);
401 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
402 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
403 key.memory_type = memory_type;
404 key.usage = usage;
405 key.size = 32 * object_size;
407 wined3d_device_vk_allocator_lock(device_vk);
409 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
411 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
412 TRACE("Using existing bo slab %p.\n", slab);
414 else
416 if (!(slab = heap_alloc_zero(sizeof(*slab))))
418 wined3d_device_vk_allocator_unlock(device_vk);
419 ERR("Failed to allocate bo slab.\n");
420 return false;
423 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
425 wined3d_device_vk_allocator_unlock(device_vk);
426 ERR("Failed to add slab to available tree.\n");
427 heap_free(slab);
428 return false;
431 slab->requested_memory_type = memory_type;
432 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
434 wined3d_device_vk_allocator_unlock(device_vk);
435 ERR("Failed to create slab bo.\n");
436 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
437 heap_free(slab);
438 return false;
440 slab->map = ~0u;
442 TRACE("Created new bo slab %p.\n", slab);
445 idx = wined3d_bit_scan(&slab->map);
446 if (!slab->map)
448 if (slab->next)
450 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
451 slab->next = NULL;
453 else
455 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
459 wined3d_device_vk_allocator_unlock(device_vk);
461 *bo = slab->bo;
462 bo->memory = NULL;
463 bo->slab = slab;
464 bo->b.client_map_count = 0;
465 bo->b.map_ptr = NULL;
466 bo->b.buffer_offset = idx * object_size;
467 bo->b.memory_offset = slab->bo.b.memory_offset + bo->b.buffer_offset;
468 bo->size = size;
469 list_init(&bo->b.users);
470 bo->command_buffer_id = 0;
471 bo->host_synced = false;
473 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
474 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
475 wine_dbgstr_longlong(bo->b.buffer_offset), bo);
477 return true;
480 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
481 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
483 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
484 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
485 VkMemoryRequirements memory_requirements;
486 struct wined3d_adapter_vk *adapter_vk;
487 VkBufferCreateInfo create_info;
488 unsigned int memory_type_idx;
489 VkResult vr;
491 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
492 return TRUE;
494 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
496 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
497 create_info.pNext = NULL;
498 create_info.flags = 0;
499 create_info.size = size;
500 create_info.usage = usage;
501 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
502 create_info.queueFamilyIndexCount = 0;
503 create_info.pQueueFamilyIndices = NULL;
505 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
507 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
508 return FALSE;
511 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
513 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
514 memory_requirements.memoryTypeBits, memory_type);
515 if (memory_type_idx == ~0u)
517 ERR("Failed to find suitable memory type.\n");
518 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
519 return FALSE;
521 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
522 memory_type_idx, memory_requirements.size, &bo->vk_memory);
523 if (!bo->vk_memory)
525 ERR("Failed to allocate buffer memory.\n");
526 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
527 return FALSE;
529 bo->b.memory_offset = bo->memory ? bo->memory->offset : 0;
531 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
532 bo->vk_memory, bo->b.memory_offset))) < 0)
534 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
535 if (bo->memory)
536 wined3d_context_vk_free_memory(context_vk, bo->memory);
537 else
538 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
539 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
540 return FALSE;
543 bo->b.client_map_count = 0;
544 bo->b.map_ptr = NULL;
545 bo->b.buffer_offset = 0;
546 bo->size = size;
547 bo->usage = usage;
548 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
549 bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
550 list_init(&bo->b.users);
551 bo->command_buffer_id = 0;
552 bo->slab = NULL;
553 bo->host_synced = false;
555 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
556 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
558 return TRUE;
561 BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkImageType vk_image_type,
562 VkImageUsageFlags usage, VkFormat vk_format, unsigned int width, unsigned int height, unsigned int depth,
563 unsigned int sample_count, unsigned int mip_levels, unsigned int layer_count, unsigned int flags,
564 struct wined3d_image_vk *image)
566 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
567 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
568 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
569 VkMemoryRequirements memory_requirements;
570 VkImageCreateInfo create_info;
571 unsigned int memory_type_idx;
572 VkResult vr;
574 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
575 create_info.pNext = NULL;
576 create_info.flags = flags;
577 create_info.imageType = vk_image_type;
578 create_info.format = vk_format;
579 create_info.extent.width = width;
580 create_info.extent.height = height;
581 create_info.extent.depth = depth;
582 create_info.mipLevels = mip_levels;
583 create_info.arrayLayers = layer_count;
584 create_info.samples = sample_count;
585 create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
586 create_info.usage = usage;
587 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
588 create_info.queueFamilyIndexCount = 0;
589 create_info.pQueueFamilyIndices = NULL;
590 create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
592 image->command_buffer_id = 0;
594 vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &image->vk_image));
595 if (vr != VK_SUCCESS)
597 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr));
598 image->vk_image = VK_NULL_HANDLE;
599 return FALSE;
602 VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image,
603 &memory_requirements));
605 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
606 memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
607 if (memory_type_idx == ~0u)
609 ERR("Failed to find suitable image memory type.\n");
610 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
611 image->vk_image = VK_NULL_HANDLE;
612 return FALSE;
615 image->memory = wined3d_context_vk_allocate_memory(context_vk, memory_type_idx,
616 memory_requirements.size, &image->vk_memory);
617 if (!image->vk_memory)
619 ERR("Failed to allocate image memory.\n");
620 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
621 image->vk_image = VK_NULL_HANDLE;
622 return FALSE;
625 vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, image->vk_memory,
626 image->memory ? image->memory->offset : 0));
627 if (vr != VK_SUCCESS)
629 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
630 if (image->memory)
631 wined3d_context_vk_free_memory(context_vk, image->memory);
632 else
633 VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
634 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
635 image->memory = NULL;
636 image->vk_memory = VK_NULL_HANDLE;
637 image->vk_image = VK_NULL_HANDLE;
638 return FALSE;
641 return TRUE;
644 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
646 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
647 struct wined3d_retired_object_vk *o;
649 if (retired->free)
651 o = retired->free;
652 retired->free = o->u.next;
653 return o;
656 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
657 retired->count + 1, sizeof(*retired->objects)))
658 return NULL;
660 return &retired->objects[retired->count++];
663 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk *context_vk,
664 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
666 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
667 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
668 struct wined3d_retired_object_vk *o;
670 if (context_vk->completed_command_buffer_id >= command_buffer_id)
672 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
673 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
674 return;
677 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
679 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
680 return;
683 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
684 o->u.vk_framebuffer = vk_framebuffer;
685 o->command_buffer_id = command_buffer_id;
688 static void wined3d_context_vk_return_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
689 VkDescriptorPool vk_descriptor_pool)
691 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
692 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
694 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
695 context_vk->vk_descriptor_pool_count + 1, sizeof(*context_vk->vk_descriptor_pools)))
697 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
698 TRACE("Destroying descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
699 return;
702 VK_CALL(vkResetDescriptorPool(device_vk->vk_device, vk_descriptor_pool, 0));
703 context_vk->vk_descriptor_pools[context_vk->vk_descriptor_pool_count++] = vk_descriptor_pool;
706 static void wined3d_context_vk_reset_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
707 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
709 struct wined3d_retired_object_vk *o;
711 if (context_vk->completed_command_buffer_id >= command_buffer_id)
713 wined3d_context_vk_return_vk_descriptor_pool(context_vk, vk_descriptor_pool);
714 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
715 return;
718 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
720 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
721 return;
724 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
725 o->u.vk_descriptor_pool = vk_descriptor_pool;
726 o->command_buffer_id = command_buffer_id;
729 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
730 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
732 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
733 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
734 struct wined3d_retired_object_vk *o;
736 if (context_vk->completed_command_buffer_id >= command_buffer_id)
738 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
739 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
740 return;
743 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
745 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
746 return;
749 o->type = WINED3D_RETIRED_MEMORY_VK;
750 o->u.vk_memory = vk_memory;
751 o->command_buffer_id = command_buffer_id;
754 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
755 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
757 struct wined3d_retired_object_vk *o;
759 if (context_vk->completed_command_buffer_id >= command_buffer_id)
761 wined3d_context_vk_free_memory(context_vk, block);
762 TRACE("Freed block %p.\n", block);
763 return;
766 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
768 ERR("Leaking block %p.\n", block);
769 return;
772 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
773 o->u.block = block;
774 o->command_buffer_id = command_buffer_id;
777 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
778 SIZE_T idx, struct wined3d_context_vk *context_vk)
780 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
781 struct wined3d_bo_slab_vk_key key;
782 struct wine_rb_entry *entry;
784 TRACE("slab %p, idx %Iu, context_vk %p.\n", slab, idx, context_vk);
786 wined3d_device_vk_allocator_lock(device_vk);
788 if (!slab->map)
790 key.memory_type = slab->requested_memory_type;
791 key.usage = slab->bo.usage;
792 key.size = slab->bo.size;
794 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
796 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
797 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
799 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
801 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
804 slab->map |= 1u << idx;
806 wined3d_device_vk_allocator_unlock(device_vk);
809 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
810 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
812 struct wined3d_retired_object_vk *o;
814 if (context_vk->completed_command_buffer_id >= command_buffer_id)
816 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
817 return;
820 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
822 ERR("Leaking slab %p, slice %#Ix.\n", slab, idx);
823 return;
826 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
827 o->u.slice.slab = slab;
828 o->u.slice.idx = idx;
829 o->command_buffer_id = command_buffer_id;
832 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk *context_vk,
833 VkBuffer vk_buffer, uint64_t command_buffer_id)
835 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
836 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
837 struct wined3d_retired_object_vk *o;
839 if (context_vk->completed_command_buffer_id >= command_buffer_id)
841 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
842 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
843 return;
846 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
848 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
849 return;
852 o->type = WINED3D_RETIRED_BUFFER_VK;
853 o->u.vk_buffer = vk_buffer;
854 o->command_buffer_id = command_buffer_id;
857 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk *context_vk,
858 VkImage vk_image, uint64_t command_buffer_id)
860 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
861 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
862 struct wined3d_retired_object_vk *o;
864 if (context_vk->completed_command_buffer_id >= command_buffer_id)
866 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
867 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
868 return;
871 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
873 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
874 return;
877 o->type = WINED3D_RETIRED_IMAGE_VK;
878 o->u.vk_image = vk_image;
879 o->command_buffer_id = command_buffer_id;
882 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk *context_vk,
883 VkBufferView vk_view, uint64_t command_buffer_id)
885 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
886 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
887 struct wined3d_retired_object_vk *o;
889 if (context_vk->completed_command_buffer_id >= command_buffer_id)
891 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
892 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
893 return;
896 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
898 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
899 return;
902 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
903 o->u.vk_buffer_view = vk_view;
904 o->command_buffer_id = command_buffer_id;
907 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk *context_vk,
908 VkImageView vk_view, uint64_t command_buffer_id)
910 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
911 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
912 struct wined3d_retired_object_vk *o;
914 if (context_vk->completed_command_buffer_id >= command_buffer_id)
916 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
917 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
918 return;
921 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
923 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
924 return;
927 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
928 o->u.vk_image_view = vk_view;
929 o->command_buffer_id = command_buffer_id;
932 static void wined3d_context_vk_reset_completed_queries(struct wined3d_context_vk *context_vk,
933 struct wined3d_query_pool_vk *pool_vk, struct wined3d_command_buffer_vk *buffer)
935 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
936 struct wined3d_retired_object_vk *o;
937 struct wined3d_range range;
938 unsigned int start = 0;
940 for (;;)
942 if (!wined3d_bitmap_get_range(pool_vk->completed, WINED3D_QUERY_POOL_SIZE, start, &range))
943 break;
945 VK_CALL(vkCmdResetQueryPool(buffer->vk_command_buffer, pool_vk->vk_query_pool, range.offset, range.size));
947 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
949 ERR("Freeing query range %u+%u in pool %p.\n", range.offset, range.size, pool_vk);
950 wined3d_query_pool_vk_mark_free(context_vk, pool_vk, range.offset, range.size);
952 else
954 o->type = WINED3D_RETIRED_QUERY_POOL_VK;
955 o->u.queries.pool_vk = pool_vk;
956 o->u.queries.start = range.offset;
957 o->u.queries.count = range.size;
958 o->command_buffer_id = buffer->id;
961 start = range.offset + range.size;
964 memset(pool_vk->completed, 0, sizeof(pool_vk->completed));
967 void wined3d_context_vk_destroy_vk_pipeline(struct wined3d_context_vk *context_vk,
968 VkPipeline vk_pipeline, uint64_t command_buffer_id)
970 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
971 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
972 struct wined3d_retired_object_vk *o;
974 if (context_vk->completed_command_buffer_id >= command_buffer_id)
976 VK_CALL(vkDestroyPipeline(device_vk->vk_device, vk_pipeline, NULL));
977 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
978 return;
981 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
983 ERR("Leaking pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
984 return;
987 o->type = WINED3D_RETIRED_PIPELINE_VK;
988 o->u.vk_pipeline = vk_pipeline;
989 o->command_buffer_id = command_buffer_id;
993 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
994 VkSampler vk_sampler, uint64_t command_buffer_id)
996 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
997 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
998 struct wined3d_retired_object_vk *o;
1000 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1002 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
1003 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1004 return;
1007 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1009 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1010 return;
1013 o->type = WINED3D_RETIRED_SAMPLER_VK;
1014 o->u.vk_sampler = vk_sampler;
1015 o->command_buffer_id = command_buffer_id;
1018 void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk,
1019 VkEvent vk_event, uint64_t command_buffer_id)
1021 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1022 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1023 struct wined3d_retired_object_vk *o;
1025 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1027 VK_CALL(vkDestroyEvent(device_vk->vk_device, vk_event, NULL));
1028 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1029 return;
1032 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1034 ERR("Leaking event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1035 return;
1038 o->type = WINED3D_RETIRED_EVENT_VK;
1039 o->u.vk_event = vk_event;
1040 o->command_buffer_id = command_buffer_id;
1043 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
1045 wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
1046 if (image->memory)
1047 wined3d_context_vk_destroy_allocator_block(context_vk, image->memory,
1048 image->command_buffer_id);
1049 else
1050 wined3d_context_vk_destroy_vk_memory(context_vk, image->vk_memory, image->command_buffer_id);
1052 image->vk_image = VK_NULL_HANDLE;
1053 image->vk_memory = VK_NULL_HANDLE;
1054 image->memory = NULL;
1057 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
1059 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1060 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1061 struct wined3d_bo_slab_vk *slab_vk;
1062 size_t object_size, idx;
1064 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
1066 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
1067 context_vk->retired_bo_size += bo->size;
1069 if ((slab_vk = bo->slab))
1071 if (bo->b.map_ptr)
1072 wined3d_bo_slab_vk_unmap(slab_vk, context_vk);
1073 object_size = slab_vk->bo.size / 32;
1074 idx = bo->b.buffer_offset / object_size;
1075 wined3d_context_vk_destroy_bo_slab_slice(context_vk, slab_vk, idx, bo->command_buffer_id);
1076 return;
1079 wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
1080 if (bo->memory)
1082 if (bo->b.map_ptr)
1083 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
1084 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
1085 return;
1088 if (bo->b.map_ptr)
1090 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
1091 adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size);
1093 wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
1096 static void wined3d_context_vk_remove_command_buffer(struct wined3d_context_vk *context_vk,
1097 unsigned int submit_index)
1099 struct wined3d_command_buffer_vk *buffer = &context_vk->submitted.buffers[submit_index];
1100 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1101 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1103 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
1104 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1105 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1107 if (buffer->id > context_vk->completed_command_buffer_id)
1108 context_vk->completed_command_buffer_id = buffer->id;
1109 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
1112 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk, VkFence vk_fence)
1114 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1115 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
1116 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1117 struct wined3d_command_buffer_vk *buffer;
1118 struct wined3d_retired_object_vk *o;
1119 uint64_t command_buffer_id;
1120 SIZE_T i = 0;
1122 while (i < context_vk->submitted.buffer_count)
1124 buffer = &context_vk->submitted.buffers[i];
1125 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
1127 ++i;
1128 continue;
1131 TRACE("Command buffer %p with id 0x%s has finished.\n",
1132 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1133 if (buffer->vk_fence == vk_fence)
1134 return;
1135 wined3d_context_vk_remove_command_buffer(context_vk, i);
1138 command_buffer_id = context_vk->completed_command_buffer_id;
1140 retired->free = NULL;
1141 for (i = retired->count; i; --i)
1143 o = &retired->objects[i - 1];
1145 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
1146 continue;
1148 switch (o->type)
1150 case WINED3D_RETIRED_FREE_VK:
1151 /* Nothing to do. */
1152 break;
1154 case WINED3D_RETIRED_FRAMEBUFFER_VK:
1155 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
1156 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
1157 break;
1159 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
1160 wined3d_context_vk_return_vk_descriptor_pool(context_vk, o->u.vk_descriptor_pool);
1161 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
1162 break;
1164 case WINED3D_RETIRED_MEMORY_VK:
1165 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
1166 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
1167 break;
1169 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
1170 TRACE("Destroying block %p.\n", o->u.block);
1171 wined3d_context_vk_free_memory(context_vk, o->u.block);
1172 break;
1174 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
1175 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
1176 break;
1178 case WINED3D_RETIRED_BUFFER_VK:
1179 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
1180 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
1181 break;
1183 case WINED3D_RETIRED_IMAGE_VK:
1184 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
1185 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
1186 break;
1188 case WINED3D_RETIRED_BUFFER_VIEW_VK:
1189 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
1190 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
1191 break;
1193 case WINED3D_RETIRED_IMAGE_VIEW_VK:
1194 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
1195 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
1196 break;
1198 case WINED3D_RETIRED_SAMPLER_VK:
1199 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
1200 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
1201 break;
1203 case WINED3D_RETIRED_QUERY_POOL_VK:
1204 wined3d_query_pool_vk_mark_free(context_vk, o->u.queries.pool_vk, o->u.queries.start, o->u.queries.count);
1205 TRACE("Freed query range %u+%u in pool %p.\n", o->u.queries.start, o->u.queries.count, o->u.queries.pool_vk);
1206 break;
1208 case WINED3D_RETIRED_EVENT_VK:
1209 VK_CALL(vkDestroyEvent(device_vk->vk_device, o->u.vk_event, NULL));
1210 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(o->u.vk_event));
1211 break;
1213 case WINED3D_RETIRED_PIPELINE_VK:
1214 VK_CALL(vkDestroyPipeline(device_vk->vk_device, o->u.vk_pipeline, NULL));
1215 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(o->u.vk_pipeline));
1216 break;
1218 default:
1219 ERR("Unhandled object type %#x.\n", o->type);
1220 break;
1223 if (i == retired->count)
1225 --retired->count;
1226 continue;
1229 o->type = WINED3D_RETIRED_FREE_VK;
1230 o->u.next = retired->free;
1231 retired->free = o;
1233 if (vk_fence && VK_CALL(vkGetFenceStatus(device_vk->vk_device, vk_fence)) != VK_NOT_READY)
1234 break;
1238 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
1240 struct wined3d_context_vk *context_vk = ctx;
1241 struct wined3d_bo_slab_vk *slab, *next;
1243 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
1244 while (slab)
1246 next = slab->next;
1247 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
1248 heap_free(slab);
1249 slab = next;
1253 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
1255 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
1256 struct wined3d_graphics_pipeline_vk, entry);
1257 struct wined3d_context_vk *context_vk = ctx;
1258 const struct wined3d_vk_info *vk_info;
1259 struct wined3d_device_vk *device_vk;
1261 vk_info = context_vk->vk_info;
1262 device_vk = wined3d_device_vk(context_vk->c.device);
1264 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
1265 heap_free(pipeline_vk);
1268 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
1270 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
1271 struct wined3d_pipeline_layout_vk, entry);
1272 struct wined3d_context_vk *context_vk = ctx;
1273 const struct wined3d_vk_info *vk_info;
1274 struct wined3d_device_vk *device_vk;
1276 vk_info = context_vk->vk_info;
1277 device_vk = wined3d_device_vk(context_vk->c.device);
1279 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
1280 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
1281 heap_free(layout->key.bindings);
1282 heap_free(layout);
1285 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
1286 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1288 struct wined3d_render_pass_attachment_vk *a;
1289 struct wined3d_rendertarget_view *view;
1290 unsigned int i;
1291 DWORD location;
1293 memset(key, 0, sizeof(*key));
1295 for (i = 0; i < rt_count; ++i)
1297 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1298 continue;
1300 a = &key->rt[i];
1301 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1302 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1303 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1304 location = wined3d_rendertarget_view_get_locations(view);
1306 if (clear_flags & WINED3DCLEAR_TARGET)
1307 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1308 else if (location & WINED3D_LOCATION_DISCARDED)
1309 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1310 else if (location & WINED3D_LOCATION_CLEARED)
1311 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1313 key->rt_mask |= 1u << i;
1316 if (depth_stencil && (view = fb->depth_stencil))
1318 a = &key->ds;
1319 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1320 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1321 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1322 location = wined3d_rendertarget_view_get_locations(view);
1323 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1325 if (clear_flags & WINED3DCLEAR_STENCIL)
1326 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S;
1327 if (clear_flags & WINED3DCLEAR_ZBUFFER)
1328 a->flags |= WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1330 if (!a->flags && (location & WINED3D_LOCATION_DISCARDED))
1331 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1332 else if (location & WINED3D_LOCATION_CLEARED)
1333 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S | WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1337 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1338 struct wined3d_context_vk *context_vk)
1340 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1341 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1343 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1346 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1347 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1349 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1350 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1351 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1352 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1353 const struct wined3d_render_pass_attachment_vk *a;
1354 VkAttachmentReference ds_attachment_reference;
1355 VkAttachmentReference *ds_reference = NULL;
1356 unsigned int attachment_count, rt_count, i;
1357 VkAttachmentDescription *attachment;
1358 VkSubpassDescription sub_pass_desc;
1359 VkRenderPassCreateInfo pass_desc;
1360 uint32_t mask;
1361 VkResult vr;
1363 rt_count = 0;
1364 attachment_count = 0;
1365 mask = key->rt_mask & wined3d_mask_from_size(WINED3D_MAX_RENDER_TARGETS);
1366 while (mask)
1368 i = wined3d_bit_scan(&mask);
1369 a = &key->rt[i];
1371 attachment = &attachments[attachment_count];
1372 attachment->flags = 0;
1373 attachment->format = a->vk_format;
1374 attachment->samples = a->vk_samples;
1376 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1377 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1378 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C)
1379 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1380 else
1381 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1383 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1384 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1385 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1386 attachment->initialLayout = a->vk_layout;
1387 attachment->finalLayout = a->vk_layout;
1389 attachment_references[i].attachment = attachment_count;
1390 attachment_references[i].layout = a->vk_layout;
1392 ++attachment_count;
1393 rt_count = i + 1;
1396 mask = ~key->rt_mask & wined3d_mask_from_size(rt_count);
1397 while (mask)
1399 i = wined3d_bit_scan(&mask);
1400 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1401 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1404 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1406 a = &key->ds;
1408 attachment = &attachments[attachment_count];
1409 attachment->flags = 0;
1410 attachment->format = a->vk_format;
1411 attachment->samples = a->vk_samples;
1413 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1414 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1415 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z)
1416 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1417 else
1418 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1420 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1421 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1422 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S)
1423 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1424 else
1425 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1427 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1428 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1429 attachment->initialLayout = a->vk_layout;
1430 attachment->finalLayout = a->vk_layout;
1432 ds_reference = &ds_attachment_reference;
1433 ds_reference->attachment = attachment_count;
1434 ds_reference->layout = a->vk_layout;
1436 ++attachment_count;
1439 sub_pass_desc.flags = 0;
1440 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1441 sub_pass_desc.inputAttachmentCount = 0;
1442 sub_pass_desc.pInputAttachments = NULL;
1443 sub_pass_desc.colorAttachmentCount = rt_count;
1444 sub_pass_desc.pColorAttachments = attachment_references;
1445 sub_pass_desc.pResolveAttachments = NULL;
1446 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1447 sub_pass_desc.preserveAttachmentCount = 0;
1448 sub_pass_desc.pPreserveAttachments = NULL;
1450 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1451 pass_desc.pNext = NULL;
1452 pass_desc.flags = 0;
1453 pass_desc.attachmentCount = attachment_count;
1454 pass_desc.pAttachments = attachments;
1455 pass_desc.subpassCount = 1;
1456 pass_desc.pSubpasses = &sub_pass_desc;
1457 pass_desc.dependencyCount = 0;
1458 pass_desc.pDependencies = NULL;
1460 pass->key = *key;
1461 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1462 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1464 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1465 return false;
1468 return true;
1471 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1472 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1474 struct wined3d_render_pass_key_vk key;
1475 struct wined3d_render_pass_vk *pass;
1476 struct wine_rb_entry *entry;
1478 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1479 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1480 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1482 if (!(pass = heap_alloc(sizeof(*pass))))
1483 return VK_NULL_HANDLE;
1485 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1487 heap_free(pass);
1488 return VK_NULL_HANDLE;
1491 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1493 ERR("Failed to insert render pass.\n");
1494 wined3d_render_pass_vk_cleanup(pass, context_vk);
1495 heap_free(pass);
1496 return VK_NULL_HANDLE;
1499 return pass->vk_render_pass;
1502 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1504 VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1505 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1506 struct wined3d_query_vk *query_vk;
1508 if (context_vk->vk_render_pass)
1510 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1511 wined3d_query_vk_suspend(query_vk, context_vk);
1513 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1514 context_vk->vk_render_pass = VK_NULL_HANDLE;
1515 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1516 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1518 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1520 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1522 ERR("Failed to allocate new query.\n");
1523 break;
1528 if (context_vk->vk_framebuffer)
1530 wined3d_context_vk_destroy_vk_framebuffer(context_vk,
1531 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1532 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1536 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1538 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1539 struct wined3d_render_pass_vk, entry);
1541 wined3d_render_pass_vk_cleanup(pass, ctx);
1542 heap_free(pass);
1545 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1547 heap_free(writes->writes);
1550 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1552 struct wined3d_query_pool_vk *pool_vk, *entry;
1554 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1556 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1557 heap_free(pool_vk);
1561 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1562 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1564 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1565 struct wined3d_query_pool_vk *pool_vk, *entry;
1566 struct wined3d_device_vk *device_vk;
1567 struct list *free_pools;
1568 VkResult vr;
1569 size_t idx;
1571 switch (type)
1573 case WINED3D_QUERY_TYPE_OCCLUSION:
1574 free_pools = &context_vk->free_occlusion_query_pools;
1575 break;
1577 case WINED3D_QUERY_TYPE_TIMESTAMP:
1578 free_pools = &context_vk->free_timestamp_query_pools;
1579 break;
1581 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1582 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1583 break;
1585 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1586 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1587 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1588 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1589 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1590 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1591 break;
1593 default:
1594 FIXME("Unhandled query type %#x.\n", type);
1595 return false;
1598 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1600 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1601 goto done;
1602 list_remove(&pool_vk->entry);
1603 list_init(&pool_vk->entry);
1606 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1607 return false;
1608 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1610 heap_free(pool_vk);
1611 return false;
1614 device_vk = wined3d_device_vk(context_vk->c.device);
1616 if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET])
1618 VK_CALL(vkResetQueryPoolEXT(device_vk->vk_device,
1619 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1621 else
1623 VkEventCreateInfo event_create_info;
1625 wined3d_context_vk_end_current_render_pass(context_vk);
1626 VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
1627 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1629 event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
1630 event_create_info.pNext = NULL;
1631 event_create_info.flags = 0;
1633 /* We probably shouldn't call vkGetQueryPoolResults() without synchronizing with vkCmdResetQueryPool()
1634 * even if the query pool is freshly allocated. wined3d_query_vk_accumulate_data() will check this event
1635 * before returning results. */
1636 vr = VK_CALL(vkCreateEvent(device_vk->vk_device, &event_create_info, NULL, &pool_vk->vk_event));
1637 if (vr == VK_SUCCESS)
1639 /* At which stage vkCmdResetQueryPool() executes? */
1640 VK_CALL(vkCmdSetEvent(wined3d_context_vk_get_command_buffer(context_vk), pool_vk->vk_event,
1641 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
1643 else
1645 ERR("Failed to create event, vr %s.\n", wined3d_debug_vkresult(vr));
1649 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1651 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1652 heap_free(pool_vk);
1653 return false;
1656 done:
1657 pool_idx->pool_vk = pool_vk;
1658 pool_idx->idx = idx;
1660 return true;
1663 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1665 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1666 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1667 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1668 unsigned int i;
1670 if (buffer->vk_command_buffer)
1672 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1673 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1674 buffer->vk_command_buffer = VK_NULL_HANDLE;
1677 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1678 context_vk->completed_command_buffer_id = buffer->id;
1680 heap_free(context_vk->compute.bindings.bindings);
1681 heap_free(context_vk->graphics.bindings.bindings);
1682 for (i = 0; i < context_vk->vk_descriptor_pool_count; ++i)
1683 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pools[i], NULL));
1684 heap_free(context_vk->vk_descriptor_pools);
1685 if (context_vk->vk_framebuffer)
1686 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1687 if (context_vk->vk_so_counter_bo.vk_buffer)
1688 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1689 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1690 /* Destroy the command pool after cleaning up resources. In particular,
1691 * this needs to happen after all command buffers are freed, because
1692 * vkFreeCommandBuffers() requires a valid pool handle. */
1693 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1694 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1695 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1696 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1697 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1698 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1699 heap_free(context_vk->submitted.buffers);
1700 heap_free(context_vk->retired.objects);
1702 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1703 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1704 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1705 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1707 wined3d_context_cleanup(&context_vk->c);
1710 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1712 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1713 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1714 VkCommandBufferAllocateInfo command_buffer_info;
1715 struct wined3d_command_buffer_vk *buffer;
1716 VkCommandBufferBeginInfo begin_info;
1717 struct wined3d_query_vk *query_vk;
1718 VkResult vr;
1720 TRACE("context_vk %p.\n", context_vk);
1722 buffer = &context_vk->current_command_buffer;
1723 if (buffer->vk_command_buffer)
1725 if (context_vk->retired_bo_size > WINED3D_RETIRED_BO_SIZE_THRESHOLD)
1726 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1727 else
1729 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1730 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1731 return buffer->vk_command_buffer;
1735 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1736 command_buffer_info.pNext = NULL;
1737 command_buffer_info.commandPool = context_vk->vk_command_pool;
1738 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1739 command_buffer_info.commandBufferCount = 1;
1740 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1741 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1743 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1744 return VK_NULL_HANDLE;
1747 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1748 begin_info.pNext = NULL;
1749 begin_info.flags = 0;
1750 begin_info.pInheritanceInfo = NULL;
1751 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1753 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1754 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1755 1, &buffer->vk_command_buffer));
1756 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1759 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1761 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1763 ERR("Failed to allocate new query.\n");
1764 break;
1767 wined3d_query_vk_resume(query_vk, context_vk);
1770 TRACE("Created new command buffer %p with id 0x%s.\n",
1771 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1773 return buffer->vk_command_buffer;
1776 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1777 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1778 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1780 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1781 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1782 struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
1783 struct wined3d_command_buffer_vk *buffer;
1784 struct wined3d_query_vk *query_vk;
1785 VkFenceCreateInfo fence_desc;
1786 VkSubmitInfo submit_info;
1787 VkResult vr;
1789 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1790 "signal_semaphore_count %u, signal_semaphores %p.\n",
1791 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1792 signal_semaphore_count, signal_semaphores);
1794 buffer = &context_vk->current_command_buffer;
1795 if (!buffer->vk_command_buffer)
1796 return;
1798 TRACE("Submitting command buffer %p with id 0x%s.\n",
1799 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1801 wined3d_context_vk_end_current_render_pass(context_vk);
1803 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
1804 struct wined3d_query_pool_vk, completed_entry)
1806 list_remove(&pool_vk->completed_entry);
1807 list_init(&pool_vk->completed_entry);
1809 wined3d_context_vk_reset_completed_queries(context_vk, pool_vk, buffer);
1812 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1813 wined3d_query_vk_suspend(query_vk, context_vk);
1815 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1816 context_vk->update_compute_pipeline = 1;
1817 context_vk->update_stream_output = 1;
1818 context_vk->c.update_shader_resource_bindings = 1;
1819 context_vk->c.update_compute_shader_resource_bindings = 1;
1820 context_vk->c.update_unordered_access_view_bindings = 1;
1821 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1822 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1823 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1824 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1825 context_invalidate_state(&context_vk->c, STATE_STENCIL_REF);
1827 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1829 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1830 fence_desc.pNext = NULL;
1831 fence_desc.flags = 0;
1832 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1833 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1835 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1836 submit_info.pNext = NULL;
1837 submit_info.waitSemaphoreCount = wait_semaphore_count;
1838 submit_info.pWaitSemaphores = wait_semaphores;
1839 submit_info.pWaitDstStageMask = wait_stages;
1840 submit_info.commandBufferCount = 1;
1841 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1842 submit_info.signalSemaphoreCount = signal_semaphore_count;
1843 submit_info.pSignalSemaphores = signal_semaphores;
1845 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1846 ERR("Failed to submit command buffer %p, vr %s.\n",
1847 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1849 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1850 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1851 ERR("Failed to grow submitted command buffer array.\n");
1853 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1855 buffer->vk_command_buffer = VK_NULL_HANDLE;
1856 /* We don't expect this to ever happen, but handle it anyway. */
1857 if (!++buffer->id)
1859 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1860 context_vk->completed_command_buffer_id = 0;
1861 buffer->id = 1;
1863 context_vk->retired_bo_size = 0;
1864 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1867 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1869 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1870 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1871 VkFence vk_fence;
1872 SIZE_T i;
1874 if (id <= context_vk->completed_command_buffer_id
1875 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1876 return;
1878 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1880 if (context_vk->submitted.buffers[i].id != id)
1881 continue;
1883 vk_fence = context_vk->submitted.buffers[i].vk_fence;
1884 wined3d_context_vk_cleanup_resources(context_vk, vk_fence);
1885 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1887 if (context_vk->submitted.buffers[i].id != id)
1888 continue;
1890 VK_CALL(vkWaitForFences(device_vk->vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX));
1891 wined3d_context_vk_remove_command_buffer(context_vk, i);
1892 return;
1896 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1899 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1900 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1901 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1902 VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range)
1904 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1905 VkImageMemoryBarrier barrier;
1907 wined3d_context_vk_end_current_render_pass(context_vk);
1909 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1910 barrier.pNext = NULL;
1911 barrier.srcAccessMask = src_access_mask;
1912 barrier.dstAccessMask = dst_access_mask;
1913 barrier.oldLayout = old_layout;
1914 barrier.newLayout = new_layout;
1915 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1916 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1917 barrier.image = image;
1918 barrier.subresourceRange = *range;
1920 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1923 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1925 const struct wined3d_render_pass_key_vk *k = key;
1926 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1927 const struct wined3d_render_pass_vk, entry);
1929 return memcmp(k, &pass->key, sizeof(*k));
1932 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1934 const struct wined3d_pipeline_layout_key_vk *a = key;
1935 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1936 const struct wined3d_pipeline_layout_vk, entry)->key;
1937 int ret;
1939 if ((ret = wined3d_uint32_compare(a->binding_count, b->binding_count)))
1940 return ret;
1941 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1944 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1946 const struct wined3d_graphics_pipeline_key_vk *a = key;
1947 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1948 const struct wined3d_graphics_pipeline_vk, entry)->key;
1949 unsigned int i;
1950 int ret;
1952 if ((ret = wined3d_uint32_compare(a->pipeline_desc.stageCount, b->pipeline_desc.stageCount)))
1953 return ret;
1954 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1956 if ((ret = wined3d_uint64_compare(a->stages[i].module, b->stages[i].module)))
1957 return ret;
1960 if ((ret = wined3d_uint32_compare(a->divisor_desc.vertexBindingDivisorCount,
1961 b->divisor_desc.vertexBindingDivisorCount)))
1962 return ret;
1963 if ((ret = memcmp(a->divisors, b->divisors,
1964 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1965 return ret;
1967 if ((ret = wined3d_uint32_compare(a->input_desc.vertexAttributeDescriptionCount,
1968 b->input_desc.vertexAttributeDescriptionCount)))
1969 return ret;
1970 if ((ret = memcmp(a->attributes, b->attributes,
1971 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1972 return ret;
1973 if ((ret = wined3d_uint32_compare(a->input_desc.vertexBindingDescriptionCount,
1974 b->input_desc.vertexBindingDescriptionCount)))
1975 return ret;
1976 if ((ret = memcmp(a->bindings, b->bindings,
1977 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1978 return ret;
1980 if ((ret = wined3d_uint32_compare(a->ia_desc.topology, b->ia_desc.topology)))
1981 return ret;
1982 if ((ret = wined3d_uint32_compare(a->ia_desc.primitiveRestartEnable, b->ia_desc.primitiveRestartEnable)))
1983 return ret;
1985 if ((ret = wined3d_uint32_compare(a->ts_desc.patchControlPoints, b->ts_desc.patchControlPoints)))
1986 return ret;
1988 if ((ret = memcmp(a->viewports, b->viewports, sizeof(a->viewports))))
1989 return ret;
1990 if ((ret = memcmp(a->scissors, b->scissors, sizeof(a->scissors))))
1991 return ret;
1993 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
1994 return ret;
1996 if ((ret = wined3d_uint32_compare(a->ms_desc.rasterizationSamples, b->ms_desc.rasterizationSamples)))
1997 return ret;
1998 if ((ret = wined3d_uint32_compare(a->ms_desc.alphaToCoverageEnable, b->ms_desc.alphaToCoverageEnable)))
1999 return ret;
2000 if ((ret = wined3d_uint32_compare(a->sample_mask, b->sample_mask)))
2001 return ret;
2003 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
2004 return ret;
2006 if ((ret = wined3d_uint32_compare(a->blend_desc.attachmentCount, b->blend_desc.attachmentCount)))
2007 return ret;
2008 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
2009 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
2010 return ret;
2012 if ((ret = wined3d_uint64_compare(a->pipeline_desc.layout, b->pipeline_desc.layout)))
2013 return ret;
2015 if ((ret = wined3d_uint64_compare(a->pipeline_desc.renderPass, b->pipeline_desc.renderPass)))
2016 return ret;
2018 return 0;
2021 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
2023 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
2024 const struct wined3d_bo_slab_vk_key *k = key;
2025 int ret;
2027 if ((ret = wined3d_uint32_compare(k->memory_type, slab->requested_memory_type)))
2028 return ret;
2029 if ((ret = wined3d_uint32_compare(k->usage, slab->bo.usage)))
2030 return ret;
2031 return wined3d_uint64_compare(k->size, slab->bo.size);
2034 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
2036 struct wined3d_graphics_pipeline_key_vk *key;
2037 VkPipelineShaderStageCreateInfo *stage;
2038 unsigned int i;
2040 static const VkDynamicState dynamic_states[] =
2042 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
2043 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
2046 key = &context_vk->graphics.pipeline_key_vk;
2047 memset(key, 0, sizeof(*key));
2049 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2051 stage = &key->stages[i];
2052 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
2053 stage->pName = "main";
2056 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
2057 key->input_desc.pVertexBindingDescriptions = key->bindings;
2058 key->input_desc.pVertexAttributeDescriptions = key->attributes;
2060 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
2061 key->divisor_desc.pVertexBindingDivisors = key->divisors;
2063 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
2065 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2067 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
2068 key->vp_desc.pViewports = key->viewports;
2069 key->vp_desc.pScissors = key->scissors;
2071 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
2072 key->rs_desc.lineWidth = 1.0f;
2074 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2075 key->ms_desc.pSampleMask = &key->sample_mask;
2077 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
2078 key->ds_desc.maxDepthBounds = 1.0f;
2080 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
2081 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
2082 key->blend_desc.pAttachments = key->blend_attachments;
2083 key->blend_desc.blendConstants[0] = 1.0f;
2084 key->blend_desc.blendConstants[1] = 1.0f;
2085 key->blend_desc.blendConstants[2] = 1.0f;
2086 key->blend_desc.blendConstants[3] = 1.0f;
2088 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2089 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
2090 key->dynamic_desc.pDynamicStates = dynamic_states;
2092 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2093 key->pipeline_desc.pStages = key->stages;
2094 key->pipeline_desc.pVertexInputState = &key->input_desc;
2095 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
2096 key->pipeline_desc.pTessellationState = &key->ts_desc;
2097 key->pipeline_desc.pViewportState = &key->vp_desc;
2098 key->pipeline_desc.pRasterizationState = &key->rs_desc;
2099 key->pipeline_desc.pMultisampleState = &key->ms_desc;
2100 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
2101 key->pipeline_desc.pColorBlendState = &key->blend_desc;
2102 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
2103 key->pipeline_desc.basePipelineIndex = -1;
2106 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
2107 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2109 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2110 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
2111 const struct wined3d_rasterizer_state_desc *r;
2112 float scale_bias;
2113 union
2115 uint32_t u32;
2116 float f32;
2117 } const_bias;
2119 if (!state->rasterizer_state)
2121 desc->depthClampEnable = VK_FALSE;
2122 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2123 desc->cullMode = VK_CULL_MODE_BACK_BIT;
2124 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
2125 desc->depthBiasEnable = VK_FALSE;
2126 desc->depthBiasConstantFactor = 0.0f;
2127 desc->depthBiasClamp = 0.0f;
2128 desc->depthBiasSlopeFactor = 0.0f;
2130 return;
2133 r = &state->rasterizer_state->desc;
2134 desc->depthClampEnable = !r->depth_clip;
2135 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2136 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
2137 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
2139 scale_bias = r->scale_bias;
2140 const_bias.f32 = r->depth_bias;
2141 if (!scale_bias && !const_bias.f32)
2143 desc->depthBiasEnable = VK_FALSE;
2144 desc->depthBiasConstantFactor = 0.0f;
2145 desc->depthBiasClamp = 0.0f;
2146 desc->depthBiasSlopeFactor = 0.0f;
2148 return;
2151 desc->depthBiasEnable = VK_TRUE;
2152 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
2154 const struct wined3d_rendertarget_view *dsv;
2156 if ((dsv = state->fb.depth_stencil))
2158 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
2159 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
2161 else
2163 desc->depthBiasConstantFactor = 0.0f;
2164 desc->depthBiasSlopeFactor = 0.0f;
2167 else
2169 desc->depthBiasConstantFactor = const_bias.f32;
2170 desc->depthBiasSlopeFactor = scale_bias;
2172 desc->depthBiasClamp = r->depth_bias_clamp;
2175 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
2176 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2178 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
2179 const struct wined3d_blend_state_desc *b;
2180 unsigned int i;
2182 desc->attachmentCount = context_vk->rt_count;
2184 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
2185 if (!state->blend_state)
2187 for (i = 0; i < context_vk->rt_count; ++i)
2189 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
2190 | VK_COLOR_COMPONENT_G_BIT
2191 | VK_COLOR_COMPONENT_B_BIT
2192 | VK_COLOR_COMPONENT_A_BIT;
2195 return;
2198 b = &state->blend_state->desc;
2199 for (i = 0; i < context_vk->rt_count; ++i)
2201 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2202 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2203 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2204 enum wined3d_blend src_blend, dst_blend;
2205 const struct wined3d_format *rt_format;
2207 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2208 if (!rt->enable)
2209 continue;
2211 if (rtv)
2212 rt_format = rtv->format;
2213 else
2214 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2215 a->blendEnable = VK_TRUE;
2217 src_blend = rt->src;
2218 dst_blend = rt->dst;
2219 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2221 src_blend = WINED3D_BLEND_SRCALPHA;
2222 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2224 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2226 src_blend = WINED3D_BLEND_INVSRCALPHA;
2227 dst_blend = WINED3D_BLEND_SRCALPHA;
2229 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2230 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2231 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2233 src_blend = rt->src_alpha;
2234 dst_blend = rt->dst_alpha;
2235 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2236 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2237 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2241 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2243 switch (component_type)
2245 case WINED3D_TYPE_UINT:
2246 return VK_FORMAT_R32G32B32A32_UINT;
2247 case WINED3D_TYPE_INT:
2248 return VK_FORMAT_R32G32B32A32_SINT;
2249 case WINED3D_TYPE_UNKNOWN:
2250 case WINED3D_TYPE_FLOAT:
2251 return VK_FORMAT_R32G32B32A32_SFLOAT;
2253 return VK_FORMAT_UNDEFINED;
2256 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2257 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2259 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2260 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2261 struct wined3d_graphics_pipeline_key_vk *key;
2262 VkPipelineShaderStageCreateInfo *stage;
2263 struct wined3d_stream_info stream_info;
2264 struct wined3d_shader *vertex_shader;
2265 VkPrimitiveTopology vk_topology;
2266 VkShaderModule module;
2267 bool update = false;
2268 uint32_t mask;
2270 *null_buffer_binding = ~0u;
2271 key = &context_vk->graphics.pipeline_key_vk;
2273 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2275 stage_count = 0;
2276 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2278 if (!(module = context_vk->graphics.vk_modules[i]))
2279 continue;
2281 stage = &key->stages[stage_count++];
2282 stage->stage = vk_shader_stage_from_wined3d(i);
2283 stage->module = module;
2286 key->pipeline_desc.stageCount = stage_count;
2288 update = true;
2291 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2292 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2293 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2295 VkVertexInputAttributeDescription *a;
2296 VkVertexInputBindingDescription *b;
2298 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2299 divisor_count = 0;
2300 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2302 VkVertexInputBindingDivisorDescriptionEXT *d;
2303 struct wined3d_stream_info_element *e;
2304 uint32_t binding;
2306 if (!(stream_info.use_map & (1u << i)))
2307 continue;
2309 a = &key->attributes[attribute_count++];
2310 e = &stream_info.elements[i];
2311 binding = e->stream_idx;
2313 a->location = i;
2314 a->binding = binding;
2315 a->format = wined3d_format_vk(e->format)->vk_format;
2316 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2318 if (mask & (1u << binding))
2319 continue;
2320 mask |= 1u << binding;
2322 b = &key->bindings[binding_count++];
2323 b->binding = binding;
2324 b->stride = e->stride;
2325 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2327 if (e->instanced)
2329 d = &key->divisors[divisor_count++];
2330 d->binding = binding;
2331 d->divisor = e->divisor;
2335 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2336 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2338 struct wined3d_shader_signature_element *element;
2339 struct wined3d_shader_signature *signature;
2340 uint32_t null_binding, location;
2342 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2344 if (!state->streams[i].buffer)
2346 null_binding = i;
2347 break;
2351 if (i == ARRAY_SIZE(state->streams))
2353 ERR("No streams left for a null buffer binding.\n");
2355 else
2357 signature = &vertex_shader->input_signature;
2358 for (i = 0; i < signature->element_count; ++i)
2360 element = &signature->elements[i];
2361 location = element->register_idx;
2363 if (!(mask & (1u << location)) || element->sysval_semantic)
2364 continue;
2365 mask &= ~(1u << location);
2367 a = &key->attributes[attribute_count++];
2368 a->location = location;
2369 a->binding = null_binding;
2370 a->format = vk_format_from_component_type(element->component_type);
2371 a->offset = 0;
2374 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2376 b = &key->bindings[binding_count++];
2377 *null_buffer_binding = b->binding = null_binding;
2378 b->stride = 0;
2379 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2384 key->input_desc.pNext = NULL;
2385 key->input_desc.vertexBindingDescriptionCount = binding_count;
2386 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2388 if (divisor_count)
2390 key->input_desc.pNext = &key->divisor_desc;
2391 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2394 update = true;
2397 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2398 if (key->ia_desc.topology != vk_topology)
2400 key->ia_desc.topology = vk_topology;
2401 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2402 && !wined3d_primitive_type_is_list(state->primitive_type);
2404 update = true;
2407 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2409 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2411 update = true;
2414 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2415 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2416 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2418 key->vp_desc.viewportCount = (context_vk->vk_info->multiple_viewports ? WINED3D_MAX_VIEWPORTS : 1);
2419 key->vp_desc.scissorCount = key->vp_desc.viewportCount;
2421 for (i = 0; i < key->vp_desc.viewportCount; ++i)
2423 const struct wined3d_viewport *src_viewport = &state->viewports[i];
2424 VkViewport *viewport = &key->viewports[i];
2425 VkRect2D *scissor = &key->scissors[i];
2427 if (i >= state->viewport_count)
2429 viewport->x = 0.0f;
2430 viewport->y = 0.0f;
2431 viewport->width = 1.0f;
2432 viewport->height = 1.0f;
2433 viewport->minDepth = 0.0f;
2434 viewport->maxDepth = 0.0f;
2436 memset(scissor, 0, sizeof(*scissor));
2437 continue;
2440 viewport->x = src_viewport->x;
2441 viewport->y = src_viewport->y;
2442 viewport->width = src_viewport->width;
2443 viewport->height = src_viewport->height;
2444 viewport->minDepth = src_viewport->min_z;
2445 viewport->maxDepth = src_viewport->max_z;
2447 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2449 const RECT *r = &state->scissor_rects[i];
2451 if (i >= state->scissor_rect_count)
2453 memset(scissor, 0, sizeof(*scissor));
2454 continue;
2457 scissor->offset.x = r->left;
2458 scissor->offset.y = r->top;
2459 scissor->extent.width = r->right - r->left;
2460 scissor->extent.height = r->bottom - r->top;
2462 else
2464 scissor->offset.x = viewport->x;
2465 scissor->offset.y = viewport->y;
2466 scissor->extent.width = viewport->width;
2467 scissor->extent.height = viewport->height;
2469 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2470 if (scissor->offset.x < 0)
2471 scissor->offset.x = 0;
2472 if (scissor->offset.y < 0)
2473 scissor->offset.y = 0;
2474 viewport->y += viewport->height;
2475 viewport->height = -viewport->height;
2478 update = true;
2481 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2482 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2484 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2486 update = true;
2489 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2490 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2492 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2493 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2494 key->sample_mask = state->sample_mask;
2496 update = true;
2499 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2500 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2502 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2504 if (d)
2506 key->ds_desc.depthTestEnable = d->desc.depth;
2507 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2508 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2509 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2510 if (key->ds_desc.stencilTestEnable)
2512 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2513 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2514 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2515 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2516 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2517 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2519 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2520 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2521 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2522 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2523 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2524 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2526 else
2528 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2529 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2532 else
2534 key->ds_desc.depthTestEnable = VK_TRUE;
2535 key->ds_desc.depthWriteEnable = VK_TRUE;
2536 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2537 key->ds_desc.stencilTestEnable = VK_FALSE;
2540 update = true;
2543 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2544 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2546 wined3d_context_vk_update_blend_state(context_vk, state, key);
2548 update = true;
2551 if (key->pipeline_desc.layout != vk_pipeline_layout)
2553 key->pipeline_desc.layout = vk_pipeline_layout;
2555 update = true;
2558 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2560 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2562 update = true;
2565 return update;
2568 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2569 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2571 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2572 VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
2573 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2574 unsigned int fb_width, fb_height, fb_layer_count;
2575 struct wined3d_rendertarget_view_vk *rtv_vk;
2576 struct wined3d_rendertarget_view *view;
2577 const VkPhysicalDeviceLimits *limits;
2578 struct wined3d_query_vk *query_vk;
2579 VkRenderPassBeginInfo begin_info;
2580 unsigned int attachment_count, i;
2581 struct wined3d_texture *texture;
2582 VkFramebufferCreateInfo fb_desc;
2583 VkResult vr;
2585 if (context_vk->vk_render_pass)
2586 return true;
2588 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2589 fb_width = limits->maxFramebufferWidth;
2590 fb_height = limits->maxFramebufferHeight;
2591 fb_layer_count = limits->maxFramebufferLayers;
2592 attachment_count = 0;
2594 context_vk->rt_count = 0;
2595 begin_info.clearValueCount = 0;
2596 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2598 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2599 continue;
2601 rtv_vk = wined3d_rendertarget_view_vk(view);
2602 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2603 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2604 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2606 if (view->width < fb_width)
2607 fb_width = view->width;
2608 if (view->height < fb_height)
2609 fb_height = view->height;
2610 if (view->layer_count < fb_layer_count)
2611 fb_layer_count = view->layer_count;
2612 context_vk->rt_count = i + 1;
2614 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2616 VkClearColorValue *c = &clear_values[attachment_count].color;
2618 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2620 c->int32[0] = c->int32[1] = c->int32[2] = c->int32[3] = 0;
2622 else
2624 texture = texture_from_resource(view->resource);
2625 wined3d_format_colour_to_vk(view->format,
2626 &texture->sub_resources[view->sub_resource_idx].clear_value.colour, c);
2629 begin_info.clearValueCount = attachment_count + 1;
2631 ++attachment_count;
2634 if ((view = state->fb.depth_stencil))
2636 rtv_vk = wined3d_rendertarget_view_vk(view);
2637 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2638 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2639 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2641 if (view->width < fb_width)
2642 fb_width = view->width;
2643 if (view->height < fb_height)
2644 fb_height = view->height;
2645 if (view->layer_count < fb_layer_count)
2646 fb_layer_count = view->layer_count;
2648 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2650 VkClearDepthStencilValue *c = &clear_values[attachment_count].depthStencil;
2652 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2654 c->depth = 0.0f;
2655 c->stencil = 0;
2657 else
2659 texture = texture_from_resource(view->resource);
2660 c->depth = texture->sub_resources[view->sub_resource_idx].clear_value.depth;
2661 c->stencil = texture->sub_resources[view->sub_resource_idx].clear_value.stencil;
2663 begin_info.clearValueCount = attachment_count + 1;
2665 ++attachment_count;
2668 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2669 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2671 ERR("Failed to get render pass.\n");
2672 return false;
2675 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2676 fb_desc.pNext = NULL;
2677 fb_desc.flags = 0;
2678 fb_desc.renderPass = context_vk->vk_render_pass;
2679 fb_desc.attachmentCount = attachment_count;
2680 fb_desc.pAttachments = vk_views;
2681 fb_desc.width = fb_width;
2682 fb_desc.height = fb_height;
2683 fb_desc.layers = fb_layer_count;
2685 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2687 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2688 return false;
2691 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2692 begin_info.pNext = NULL;
2693 begin_info.renderPass = context_vk->vk_render_pass;
2694 begin_info.framebuffer = context_vk->vk_framebuffer;
2695 begin_info.renderArea.offset.x = 0;
2696 begin_info.renderArea.offset.y = 0;
2697 begin_info.renderArea.extent.width = fb_width;
2698 begin_info.renderArea.extent.height = fb_height;
2699 begin_info.pClearValues = clear_values;
2700 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2702 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2703 wined3d_query_vk_resume(query_vk, context_vk);
2704 return true;
2707 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2708 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2710 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2711 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2712 const struct wined3d_stream_state *stream;
2713 const VkDescriptorBufferInfo *buffer_info;
2714 struct wined3d_buffer_vk *buffer_vk;
2715 struct wined3d_buffer *buffer;
2716 unsigned int i, first, count;
2718 first = 0;
2719 count = 0;
2720 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2722 stream = &state->streams[i];
2724 if ((buffer = stream->buffer))
2726 buffer_vk = wined3d_buffer_vk(buffer);
2727 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2728 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2729 buffers[count] = buffer_info->buffer;
2730 offsets[count] = buffer_info->offset + stream->offset;
2731 ++count;
2732 continue;
2735 if (count)
2736 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2737 first = i + 1;
2738 count = 0;
2741 if (count)
2742 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2745 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2746 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2748 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2749 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2750 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2751 const struct wined3d_stream_output *stream;
2752 const VkDescriptorBufferInfo *buffer_info;
2753 struct wined3d_buffer_vk *buffer_vk;
2754 struct wined3d_buffer *buffer;
2755 unsigned int i, first, count;
2757 first = 0;
2758 count = 0;
2759 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2761 stream = &state->stream_output[i];
2763 if ((buffer = stream->buffer))
2765 buffer_vk = wined3d_buffer_vk(buffer);
2766 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2767 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2768 buffers[count] = buffer_info->buffer;
2769 if ((offsets[count] = stream->offset) == ~0u)
2771 FIXME("Appending to stream output buffers not implemented.\n");
2772 offsets[count] = 0;
2774 sizes[count] = buffer_info->range - offsets[count];
2775 offsets[count] += buffer_info->offset;
2776 ++count;
2777 continue;
2780 if (count)
2781 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2782 first = i + 1;
2783 count = 0;
2786 if (count)
2787 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2790 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2791 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2793 struct VkDescriptorPoolCreateInfo pool_desc;
2794 VkResult vr;
2796 static const VkDescriptorPoolSize pool_sizes[] =
2798 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2799 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2800 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2801 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2802 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2803 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2806 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2807 pool_desc.pNext = NULL;
2808 pool_desc.flags = 0;
2809 pool_desc.maxSets = 512;
2810 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2811 pool_desc.pPoolSizes = pool_sizes;
2813 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2814 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2816 return vr;
2819 VkDescriptorPool wined3d_context_vk_get_vk_descriptor_pool(struct wined3d_context_vk *context_vk)
2821 VkResult vr;
2823 if (context_vk->vk_descriptor_pool_count)
2824 return context_vk->vk_descriptor_pools[0];
2826 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
2827 1, sizeof(*context_vk->vk_descriptor_pools)))
2829 ERR("Failed to allocate array.\n");
2830 return VK_NULL_HANDLE;
2833 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(wined3d_device_vk(context_vk->c.device),
2834 context_vk->vk_info, context_vk->vk_descriptor_pools)))
2836 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2837 return VK_NULL_HANDLE;
2840 context_vk->vk_descriptor_pool_count = 1;
2841 return context_vk->vk_descriptor_pools[0];
2844 VkDescriptorSet wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2845 VkDescriptorSetLayout vk_set_layout)
2847 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2848 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2849 struct VkDescriptorSetAllocateInfo set_desc;
2850 VkDescriptorPool vk_descriptor_pool;
2851 VkDescriptorSet vk_descriptor_set;
2852 VkResult vr;
2854 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2855 return VK_NULL_HANDLE;
2857 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2858 set_desc.pNext = NULL;
2859 set_desc.descriptorPool = vk_descriptor_pool;
2860 set_desc.descriptorSetCount = 1;
2861 set_desc.pSetLayouts = &vk_set_layout;
2862 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2863 return vk_descriptor_set;
2865 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2867 wined3d_context_vk_reset_vk_descriptor_pool(context_vk,
2868 vk_descriptor_pool, context_vk->current_command_buffer.id);
2869 context_vk->vk_descriptor_pools[0] = context_vk->vk_descriptor_pools[--context_vk->vk_descriptor_pool_count];
2870 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2872 WARN("Failed to create descriptor pool.\n");
2873 return VK_NULL_HANDLE;
2876 set_desc.descriptorPool = vk_descriptor_pool;
2877 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2878 return vk_descriptor_set;
2881 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2883 return VK_NULL_HANDLE;
2886 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2887 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2888 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2889 const VkBufferView *buffer_view)
2891 SIZE_T write_count = writes->count;
2892 VkWriteDescriptorSet *write;
2894 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2895 write_count + 1, sizeof(*writes->writes)))
2896 return false;
2898 write = &writes->writes[write_count];
2899 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2900 write->pNext = NULL;
2901 write->dstSet = vk_descriptor_set;
2902 write->dstBinding = binding_idx;
2903 write->dstArrayElement = 0;
2904 write->descriptorCount = 1;
2905 write->descriptorType = type;
2906 write->pImageInfo = image_info;
2907 write->pBufferInfo = buffer_info;
2908 write->pTexelBufferView = buffer_view;
2910 ++writes->count;
2912 return true;
2915 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2916 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2917 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2919 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2921 switch (type)
2923 case WINED3D_SHADER_RESOURCE_BUFFER:
2924 if (data_type == WINED3D_DATA_FLOAT)
2925 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2926 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2927 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2928 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2930 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2931 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2932 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2934 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2935 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2936 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2938 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2939 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2940 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2942 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2943 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2944 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2946 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2947 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2948 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2950 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2951 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2952 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
2954 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2955 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2956 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2958 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2959 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2960 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2962 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
2963 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2964 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube_array, NULL);
2966 default:
2967 FIXME("Unhandled resource type %#x.\n", type);
2968 return false;
2972 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2973 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2974 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
2976 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
2977 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2978 struct wined3d_buffer_vk *buffer_vk;
2979 struct wined3d_buffer *buffer;
2981 if (!(buffer = cb_state->buffer))
2982 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2983 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
2985 buffer_vk = wined3d_buffer_vk(buffer);
2986 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
2987 buffer_info->offset += cb_state->offset;
2988 buffer_info->range = min(cb_state->size, buffer_info->range);
2989 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2990 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
2991 return false;
2992 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2993 return true;
2996 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2997 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2998 const struct wined3d_shader_resource_binding *binding)
3000 struct wined3d_shader_resource_view_vk *srv_vk;
3001 struct wined3d_shader_resource_view *srv;
3002 const VkDescriptorImageInfo *image_info;
3003 struct wined3d_resource *resource;
3004 struct wined3d_view_vk *view_vk;
3005 VkBufferView *buffer_view;
3006 VkDescriptorType type;
3008 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3009 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
3010 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
3012 resource = srv->resource;
3013 srv_vk = wined3d_shader_resource_view_vk(srv);
3014 view_vk = &srv_vk->view_vk;
3015 if (resource->type == WINED3D_RTYPE_BUFFER)
3017 image_info = NULL;
3018 buffer_view = &view_vk->u.vk_buffer_view;
3019 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
3021 else
3023 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3025 if (view_vk->u.vk_image_info.imageView)
3026 image_info = &view_vk->u.vk_image_info;
3027 else
3028 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3029 buffer_view = NULL;
3030 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3033 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3034 binding->binding_idx, type, NULL, image_info, buffer_view))
3035 return false;
3036 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
3037 return true;
3040 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
3041 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3042 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3044 struct wined3d_unordered_access_view_vk *uav_vk;
3045 struct wined3d_unordered_access_view *uav;
3046 const VkDescriptorImageInfo *image_info;
3047 struct wined3d_resource *resource;
3048 struct wined3d_view_vk *view_vk;
3049 VkBufferView *buffer_view;
3050 VkDescriptorType type;
3052 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3054 FIXME("NULL unordered access views not implemented.\n");
3055 return false;
3057 resource = uav->resource;
3059 uav_vk = wined3d_unordered_access_view_vk(uav);
3060 view_vk = &uav_vk->view_vk;
3061 if (resource->type == WINED3D_RTYPE_BUFFER)
3063 image_info = NULL;
3064 buffer_view = &view_vk->u.vk_buffer_view;
3065 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
3067 else
3069 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3071 if (view_vk->u.vk_image_info.imageView)
3072 image_info = &view_vk->u.vk_image_info;
3073 else
3074 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3075 buffer_view = NULL;
3076 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3079 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3080 binding->binding_idx, type, NULL, image_info, buffer_view))
3081 return false;
3082 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
3083 return true;
3086 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
3087 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
3088 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3089 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3091 struct wined3d_unordered_access_view_vk *uav_vk;
3092 struct wined3d_unordered_access_view *uav;
3094 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3096 FIXME("NULL unordered access view counters not implemented.\n");
3097 return false;
3100 uav_vk = wined3d_unordered_access_view_vk(uav);
3101 if (!uav_vk->vk_counter_view)
3102 return false;
3104 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3105 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
3108 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
3109 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3110 const struct wined3d_shader_resource_binding *binding)
3112 struct wined3d_sampler *sampler;
3114 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3115 sampler = context_vk->c.device->null_sampler;
3116 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3117 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
3118 return false;
3119 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
3120 return true;
3123 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
3124 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3126 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3127 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
3128 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3129 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3130 const struct wined3d_shader_resource_binding *binding;
3131 struct wined3d_shader_resource_bindings *bindings;
3132 VkDescriptorSetLayout vk_set_layout;
3133 VkPipelineLayout vk_pipeline_layout;
3134 VkPipelineBindPoint vk_bind_point;
3135 VkDescriptorSet vk_descriptor_set;
3136 size_t i;
3138 switch (pipeline)
3140 case WINED3D_PIPELINE_GRAPHICS:
3141 bindings = &context_vk->graphics.bindings;
3142 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
3143 vk_set_layout = context_vk->graphics.vk_set_layout;
3144 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
3145 break;
3147 case WINED3D_PIPELINE_COMPUTE:
3148 bindings = &context_vk->compute.bindings;
3149 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
3150 vk_set_layout = context_vk->compute.vk_set_layout;
3151 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
3152 break;
3154 default:
3155 ERR("Invalid pipeline %#x.\n", pipeline);
3156 return false;
3159 if (!(vk_descriptor_set = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout)))
3161 WARN("Failed to create descriptor set.\n");
3162 return false;
3165 writes->count = 0;
3166 for (i = 0; i < bindings->count; ++i)
3168 binding = &bindings->bindings[i];
3170 switch (binding->shader_descriptor_type)
3172 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3173 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
3174 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
3175 return false;
3176 break;
3178 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3179 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
3180 context_vk, vk_descriptor_set, state, binding))
3181 return false;
3182 break;
3184 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3185 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
3186 context_vk, pipeline, vk_descriptor_set, state, binding))
3187 return false;
3188 break;
3190 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3191 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
3192 context_vk, pipeline, vk_descriptor_set, state, binding))
3193 return false;
3194 break;
3196 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3197 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
3198 context_vk, vk_descriptor_set, state, binding))
3199 return false;
3200 break;
3202 default:
3203 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3204 return false;
3208 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
3209 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
3210 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
3212 return true;
3215 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
3216 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
3217 VkDescriptorSetLayout *vk_set_layout)
3219 VkDescriptorSetLayoutCreateInfo layout_desc;
3220 VkResult vr;
3222 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3223 layout_desc.pNext = NULL;
3224 layout_desc.flags = 0;
3225 layout_desc.bindingCount = key->binding_count;
3226 layout_desc.pBindings = key->bindings;
3228 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
3229 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3231 return vr;
3234 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
3235 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
3237 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3238 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3239 struct wined3d_pipeline_layout_key_vk key;
3240 struct wined3d_pipeline_layout_vk *layout;
3241 VkPipelineLayoutCreateInfo layout_desc;
3242 struct wine_rb_entry *entry;
3243 VkResult vr;
3245 key.bindings = bindings;
3246 key.binding_count = binding_count;
3247 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
3248 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
3250 if (!(layout = heap_alloc(sizeof(*layout))))
3251 return NULL;
3253 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
3255 heap_free(layout);
3256 return NULL;
3258 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
3259 layout->key.binding_count = key.binding_count;
3261 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
3263 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3264 goto fail;
3267 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3268 layout_desc.pNext = NULL;
3269 layout_desc.flags = 0;
3270 layout_desc.setLayoutCount = 1;
3271 layout_desc.pSetLayouts = &layout->vk_set_layout;
3272 layout_desc.pushConstantRangeCount = 0;
3273 layout_desc.pPushConstantRanges = NULL;
3275 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
3276 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
3278 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
3279 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3280 goto fail;
3283 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
3285 ERR("Failed to insert pipeline layout.\n");
3286 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3287 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3288 goto fail;
3291 return layout;
3293 fail:
3294 heap_free(layout->key.bindings);
3295 heap_free(layout);
3296 return NULL;
3299 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3301 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3302 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3303 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3304 struct wined3d_graphics_pipeline_key_vk *key;
3305 struct wine_rb_entry *entry;
3306 VkResult vr;
3308 key = &context_vk->graphics.pipeline_key_vk;
3309 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3310 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3312 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3313 return VK_NULL_HANDLE;
3314 pipeline_vk->key = *key;
3316 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3317 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3319 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3320 heap_free(pipeline_vk);
3321 return VK_NULL_HANDLE;
3324 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3325 ERR("Failed to insert pipeline.\n");
3327 return pipeline_vk->vk_pipeline;
3330 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3331 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3333 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3334 const struct wined3d_shader_resource_bindings *bindings;
3335 const struct wined3d_shader_resource_binding *binding;
3336 struct wined3d_unordered_access_view_vk *uav_vk;
3337 struct wined3d_shader_resource_view_vk *srv_vk;
3338 struct wined3d_unordered_access_view *uav;
3339 struct wined3d_shader_resource_view *srv;
3340 struct wined3d_buffer_vk *buffer_vk;
3341 struct wined3d_sampler *sampler;
3342 struct wined3d_buffer *buffer;
3343 size_t i;
3345 switch (pipeline)
3347 case WINED3D_PIPELINE_GRAPHICS:
3348 bindings = &context_vk->graphics.bindings;
3349 break;
3351 case WINED3D_PIPELINE_COMPUTE:
3352 bindings = &context_vk->compute.bindings;
3353 break;
3355 default:
3356 ERR("Invalid pipeline %#x.\n", pipeline);
3357 return;
3360 writes->count = 0;
3361 for (i = 0; i < bindings->count; ++i)
3363 binding = &bindings->bindings[i];
3365 switch (binding->shader_descriptor_type)
3367 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3368 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3369 break;
3371 buffer_vk = wined3d_buffer_vk(buffer);
3372 wined3d_buffer_load(buffer, &context_vk->c, state);
3373 if (!buffer_vk->b.bo_user.valid)
3375 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3376 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3377 else
3378 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3380 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3381 break;
3383 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3384 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3385 break;
3387 srv_vk = wined3d_shader_resource_view_vk(srv);
3388 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3390 if (!srv_vk->view_vk.bo_user.valid)
3392 wined3d_shader_resource_view_vk_update(srv_vk, context_vk);
3393 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3394 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3395 else
3396 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3398 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3400 else
3402 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3404 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3405 break;
3407 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3408 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3409 break;
3411 uav_vk = wined3d_unordered_access_view_vk(uav);
3412 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3414 if (!uav_vk->view_vk.bo_user.valid)
3416 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3417 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3418 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3419 else
3420 context_invalidate_compute_state(&context_vk->c,
3421 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3423 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3424 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3426 else
3428 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3429 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3431 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3432 break;
3434 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3435 break;
3437 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3438 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3439 sampler = context_vk->c.device->null_sampler;
3440 break;
3442 default:
3443 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3444 break;
3449 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3450 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3452 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3453 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3454 const struct wined3d_blend_state *b = state->blend_state;
3455 bool dual_source_blend = b && b->dual_source;
3456 struct wined3d_rendertarget_view *dsv;
3457 struct wined3d_rendertarget_view *rtv;
3458 struct wined3d_buffer_vk *buffer_vk;
3459 VkSampleCountFlagBits sample_count;
3460 VkCommandBuffer vk_command_buffer;
3461 unsigned int i, invalidate_rt = 0;
3462 struct wined3d_buffer *buffer;
3463 uint32_t null_buffer_binding;
3464 bool invalidate_ds = false;
3466 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3467 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)
3468 || dual_source_blend != context_vk->c.last_was_dual_source_blend)
3470 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3471 context_vk->c.last_was_dual_source_blend = dual_source_blend;
3473 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3474 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3475 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3476 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3477 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3478 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3479 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3480 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3482 context_vk->sample_count = 0;
3483 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3485 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3486 continue;
3488 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3490 /* We handle clears at the beginning of the render pass, no need for an explicit clear
3491 * first. */
3492 if (wined3d_rendertarget_view_get_locations(rtv) & WINED3D_LOCATION_CLEARED)
3493 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3494 else
3495 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3496 invalidate_rt |= (1 << i);
3498 else
3500 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3503 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3504 if (!context_vk->sample_count)
3505 context_vk->sample_count = sample_count;
3506 else if (context_vk->sample_count != sample_count)
3507 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3510 if ((dsv = state->fb.depth_stencil))
3512 if (wined3d_state_uses_depth_buffer(state))
3514 if (wined3d_rendertarget_view_get_locations(dsv) & WINED3D_LOCATION_CLEARED)
3515 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3516 else
3517 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3519 else
3521 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3524 if (!state->depth_stencil_state || state->depth_stencil_state->writes_ds)
3525 invalidate_ds = true;
3527 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3528 if (!context_vk->sample_count)
3529 context_vk->sample_count = sample_count;
3530 else if (context_vk->sample_count != sample_count)
3531 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3534 if (!context_vk->sample_count)
3535 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3536 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3538 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3539 if (!context_vk->graphics.vk_pipeline_layout)
3541 ERR("No pipeline layout set.\n");
3542 return VK_NULL_HANDLE;
3544 context_vk->c.update_shader_resource_bindings = 1;
3545 context_vk->c.update_unordered_access_view_bindings = 1;
3548 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3550 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3552 if (!(buffer = state->streams[i].buffer))
3553 continue;
3555 buffer_vk = wined3d_buffer_vk(buffer);
3556 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3557 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3558 if (!buffer_vk->b.bo_user.valid)
3559 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3562 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3564 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3566 if (!(buffer = state->stream_output[i].buffer))
3567 continue;
3569 buffer_vk = wined3d_buffer_vk(buffer);
3570 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3571 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3572 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3573 if (!buffer_vk->b.bo_user.valid)
3574 context_vk->update_stream_output = 1;
3576 context_vk->c.transform_feedback_active = 1;
3579 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3581 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3582 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3583 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3584 if (!buffer_vk->b.bo_user.valid)
3585 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3588 if (indirect_vk)
3590 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3591 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3594 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3596 ERR("Failed to get command buffer.\n");
3597 return VK_NULL_HANDLE;
3600 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3601 wined3d_context_vk_end_current_render_pass(context_vk);
3602 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3604 ERR("Failed to begin render pass.\n");
3605 return VK_NULL_HANDLE;
3608 while (invalidate_rt)
3610 i = wined3d_bit_scan(&invalidate_rt);
3611 rtv = state->fb.render_targets[i];
3612 wined3d_rendertarget_view_validate_location(rtv, rtv->resource->draw_binding);
3613 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3616 if (invalidate_ds)
3618 wined3d_rendertarget_view_validate_location(dsv, dsv->resource->draw_binding);
3619 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3622 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3623 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3625 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3627 ERR("Failed to get graphics pipeline.\n");
3628 return VK_NULL_HANDLE;
3631 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3632 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3633 if (null_buffer_binding != ~0u)
3635 VkDeviceSize offset = 0;
3636 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3637 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3641 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3643 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3644 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3647 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3648 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3650 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3652 context_vk->update_stream_output = 1;
3653 context_vk->c.transform_feedback_paused = 0;
3655 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3657 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3658 context_vk->update_stream_output = 0;
3661 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3663 const VkDescriptorBufferInfo *buffer_info;
3664 VkIndexType idx_type;
3666 if (state->index_format == WINED3DFMT_R16_UINT)
3667 idx_type = VK_INDEX_TYPE_UINT16;
3668 else
3669 idx_type = VK_INDEX_TYPE_UINT32;
3670 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3671 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3672 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer_vk->b.buffer_object));
3673 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3674 buffer_info->offset + state->index_offset, idx_type));
3677 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3678 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3679 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3680 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3681 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3682 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3683 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3684 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3685 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3686 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3687 context_vk->c.update_shader_resource_bindings = 1;
3688 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3689 context_vk->c.update_unordered_access_view_bindings = 1;
3691 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3693 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3695 ERR("Failed to update shader descriptors.\n");
3696 return VK_NULL_HANDLE;
3699 context_vk->c.update_shader_resource_bindings = 0;
3700 context_vk->c.update_unordered_access_view_bindings = 0;
3703 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3704 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3706 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3707 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3709 return vk_command_buffer;
3712 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3713 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3715 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3716 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3717 VkCommandBuffer vk_command_buffer;
3719 wined3d_context_vk_end_current_render_pass(context_vk);
3721 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3722 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3724 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3726 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3727 if (!context_vk->compute.vk_pipeline)
3729 ERR("No compute pipeline set.\n");
3730 return VK_NULL_HANDLE;
3732 context_vk->c.update_compute_shader_resource_bindings = 1;
3733 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3734 context_vk->update_compute_pipeline = 1;
3737 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3739 if (indirect_vk)
3741 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3742 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3745 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3747 ERR("Failed to get command buffer.\n");
3748 return VK_NULL_HANDLE;
3751 if (context_vk->update_compute_pipeline)
3753 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3754 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3755 context_vk->update_compute_pipeline = 0;
3758 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3759 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3760 context_vk->c.update_compute_shader_resource_bindings = 1;
3761 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3762 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3764 if (context_vk->c.update_compute_shader_resource_bindings
3765 || context_vk->c.update_compute_unordered_access_view_bindings)
3767 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3769 ERR("Failed to update shader descriptors.\n");
3770 return VK_NULL_HANDLE;
3773 context_vk->c.update_compute_shader_resource_bindings = 0;
3774 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3777 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3778 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3780 return vk_command_buffer;
3783 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3785 VkCommandPoolCreateInfo command_pool_info;
3786 const struct wined3d_vk_info *vk_info;
3787 struct wined3d_adapter_vk *adapter_vk;
3788 struct wined3d_device_vk *device_vk;
3789 VkResult vr;
3791 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3793 memset(context_vk, 0, sizeof(*context_vk));
3794 wined3d_context_init(&context_vk->c, swapchain);
3795 device_vk = wined3d_device_vk(swapchain->device);
3796 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3797 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3799 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3800 command_pool_info.pNext = NULL;
3801 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3802 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3803 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3804 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3806 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3807 wined3d_context_cleanup(&context_vk->c);
3808 return E_FAIL;
3810 context_vk->current_command_buffer.id = 1;
3812 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3814 list_init(&context_vk->render_pass_queries);
3815 list_init(&context_vk->active_queries);
3816 list_init(&context_vk->completed_query_pools);
3817 list_init(&context_vk->free_occlusion_query_pools);
3818 list_init(&context_vk->free_timestamp_query_pools);
3819 list_init(&context_vk->free_pipeline_statistics_query_pools);
3820 list_init(&context_vk->free_stream_output_statistics_query_pools);
3822 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3823 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3824 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3825 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3827 return WINED3D_OK;