mscoree/tests: Test querying interfaces with generated GUID.
[wine.git] / dlls / wined3d / context_vk.c
blobf1258842152f10700dbddb9cccda82dca25167c0
1 /*
2 * Copyright 2002-2004 Jason Edmeades
3 * Copyright 2002-2004 Raphael Junqueira
4 * Copyright 2004 Christian Costa
5 * Copyright 2005 Oliver Stieber
6 * Copyright 2006, 2008 Henri Verbeet
7 * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
8 * Copyright 2009-2020 Henri Verbeet for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "config.h"
26 #include "wine/port.h"
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
32 VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op)
34 switch (op)
36 case WINED3D_CMP_NEVER:
37 return VK_COMPARE_OP_NEVER;
38 case WINED3D_CMP_LESS:
39 return VK_COMPARE_OP_LESS;
40 case WINED3D_CMP_EQUAL:
41 return VK_COMPARE_OP_EQUAL;
42 case WINED3D_CMP_LESSEQUAL:
43 return VK_COMPARE_OP_LESS_OR_EQUAL;
44 case WINED3D_CMP_GREATER:
45 return VK_COMPARE_OP_GREATER;
46 case WINED3D_CMP_NOTEQUAL:
47 return VK_COMPARE_OP_NOT_EQUAL;
48 case WINED3D_CMP_GREATEREQUAL:
49 return VK_COMPARE_OP_GREATER_OR_EQUAL;
50 case WINED3D_CMP_ALWAYS:
51 return VK_COMPARE_OP_ALWAYS;
52 default:
53 if (!op)
54 WARN("Unhandled compare operation %#x.\n", op);
55 else
56 FIXME("Unhandled compare operation %#x.\n", op);
57 return VK_COMPARE_OP_NEVER;
61 VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type)
63 switch (shader_type)
65 case WINED3D_SHADER_TYPE_VERTEX:
66 return VK_SHADER_STAGE_VERTEX_BIT;
67 case WINED3D_SHADER_TYPE_HULL:
68 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
69 case WINED3D_SHADER_TYPE_DOMAIN:
70 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
71 case WINED3D_SHADER_TYPE_GEOMETRY:
72 return VK_SHADER_STAGE_GEOMETRY_BIT;
73 case WINED3D_SHADER_TYPE_PIXEL:
74 return VK_SHADER_STAGE_FRAGMENT_BIT;
75 case WINED3D_SHADER_TYPE_COMPUTE:
76 return VK_SHADER_STAGE_COMPUTE_BIT;
77 default:
78 ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type));
79 return 0;
83 static VkBlendFactor vk_blend_factor_from_wined3d(enum wined3d_blend blend,
84 const struct wined3d_format *dst_format, bool alpha)
86 switch (blend)
88 case WINED3D_BLEND_ZERO:
89 return VK_BLEND_FACTOR_ZERO;
90 case WINED3D_BLEND_ONE:
91 return VK_BLEND_FACTOR_ONE;
92 case WINED3D_BLEND_SRCCOLOR:
93 return VK_BLEND_FACTOR_SRC_COLOR;
94 case WINED3D_BLEND_INVSRCCOLOR:
95 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
96 case WINED3D_BLEND_SRCALPHA:
97 return VK_BLEND_FACTOR_SRC_ALPHA;
98 case WINED3D_BLEND_INVSRCALPHA:
99 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
100 case WINED3D_BLEND_DESTALPHA:
101 if (dst_format->alpha_size)
102 return VK_BLEND_FACTOR_DST_ALPHA;
103 return VK_BLEND_FACTOR_ONE;
104 case WINED3D_BLEND_INVDESTALPHA:
105 if (dst_format->alpha_size)
106 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
107 return VK_BLEND_FACTOR_ZERO;
108 case WINED3D_BLEND_DESTCOLOR:
109 return VK_BLEND_FACTOR_DST_COLOR;
110 case WINED3D_BLEND_INVDESTCOLOR:
111 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
112 case WINED3D_BLEND_SRCALPHASAT:
113 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
114 case WINED3D_BLEND_BLENDFACTOR:
115 if (alpha)
116 return VK_BLEND_FACTOR_CONSTANT_ALPHA;
117 return VK_BLEND_FACTOR_CONSTANT_COLOR;
118 case WINED3D_BLEND_INVBLENDFACTOR:
119 if (alpha)
120 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
121 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
122 case WINED3D_BLEND_SRC1COLOR:
123 return VK_BLEND_FACTOR_SRC1_COLOR;
124 case WINED3D_BLEND_INVSRC1COLOR:
125 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
126 case WINED3D_BLEND_SRC1ALPHA:
127 return VK_BLEND_FACTOR_SRC1_ALPHA;
128 case WINED3D_BLEND_INVSRC1ALPHA:
129 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
130 default:
131 FIXME("Unhandled blend %#x.\n", blend);
132 return VK_BLEND_FACTOR_ZERO;
136 static VkBlendOp vk_blend_op_from_wined3d(enum wined3d_blend_op op)
138 switch (op)
140 case WINED3D_BLEND_OP_ADD:
141 return VK_BLEND_OP_ADD;
142 case WINED3D_BLEND_OP_SUBTRACT:
143 return VK_BLEND_OP_SUBTRACT;
144 case WINED3D_BLEND_OP_REVSUBTRACT:
145 return VK_BLEND_OP_REVERSE_SUBTRACT;
146 case WINED3D_BLEND_OP_MIN:
147 return VK_BLEND_OP_MIN;
148 case WINED3D_BLEND_OP_MAX:
149 return VK_BLEND_OP_MAX;
150 default:
151 FIXME("Unhandled blend op %#x.\n", op);
152 return VK_BLEND_OP_ADD;
156 static VkColorComponentFlags vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask)
158 VkColorComponentFlags vk_mask = 0;
160 if (wined3d_mask & WINED3DCOLORWRITEENABLE_RED)
161 vk_mask |= VK_COLOR_COMPONENT_R_BIT;
162 if (wined3d_mask & WINED3DCOLORWRITEENABLE_GREEN)
163 vk_mask |= VK_COLOR_COMPONENT_G_BIT;
164 if (wined3d_mask & WINED3DCOLORWRITEENABLE_BLUE)
165 vk_mask |= VK_COLOR_COMPONENT_B_BIT;
166 if (wined3d_mask & WINED3DCOLORWRITEENABLE_ALPHA)
167 vk_mask |= VK_COLOR_COMPONENT_A_BIT;
169 return vk_mask;
172 static VkCullModeFlags vk_cull_mode_from_wined3d(enum wined3d_cull mode)
174 switch (mode)
176 case WINED3D_CULL_NONE:
177 return VK_CULL_MODE_NONE;
178 case WINED3D_CULL_FRONT:
179 return VK_CULL_MODE_FRONT_BIT;
180 case WINED3D_CULL_BACK:
181 return VK_CULL_MODE_BACK_BIT;
182 default:
183 FIXME("Unhandled cull mode %#x.\n", mode);
184 return VK_CULL_MODE_NONE;
188 static VkPrimitiveTopology vk_topology_from_wined3d(enum wined3d_primitive_type t)
190 switch (t)
192 case WINED3D_PT_POINTLIST:
193 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
194 case WINED3D_PT_LINELIST:
195 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
196 case WINED3D_PT_LINESTRIP:
197 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
198 case WINED3D_PT_TRIANGLELIST:
199 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
200 case WINED3D_PT_TRIANGLESTRIP:
201 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
202 case WINED3D_PT_TRIANGLEFAN:
203 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
204 case WINED3D_PT_LINELIST_ADJ:
205 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
206 case WINED3D_PT_LINESTRIP_ADJ:
207 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
208 case WINED3D_PT_TRIANGLELIST_ADJ:
209 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
210 case WINED3D_PT_TRIANGLESTRIP_ADJ:
211 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
212 case WINED3D_PT_PATCH:
213 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
214 default:
215 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t));
216 case WINED3D_PT_UNDEFINED:
217 return ~0u;
221 static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op)
223 switch (op)
225 case WINED3D_STENCIL_OP_KEEP:
226 return VK_STENCIL_OP_KEEP;
227 case WINED3D_STENCIL_OP_ZERO:
228 return VK_STENCIL_OP_ZERO;
229 case WINED3D_STENCIL_OP_REPLACE:
230 return VK_STENCIL_OP_REPLACE;
231 case WINED3D_STENCIL_OP_INCR_SAT:
232 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
233 case WINED3D_STENCIL_OP_DECR_SAT:
234 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
235 case WINED3D_STENCIL_OP_INVERT:
236 return VK_STENCIL_OP_INVERT;
237 case WINED3D_STENCIL_OP_INCR:
238 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
239 case WINED3D_STENCIL_OP_DECR:
240 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
241 default:
242 if (!op)
243 WARN("Unhandled stencil operation %#x.\n", op);
244 else
245 FIXME("Unhandled stencil operation %#x.\n", op);
246 return VK_STENCIL_OP_KEEP;
250 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
251 struct wined3d_context_vk *context_vk)
253 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
254 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
255 VkResult vr;
257 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
258 wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
260 if (!chunk_vk->c.map_ptr && (vr = VK_CALL(vkMapMemory(device_vk->vk_device,
261 chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
263 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
264 return NULL;
267 ++chunk_vk->c.map_count;
269 return chunk_vk->c.map_ptr;
272 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
273 struct wined3d_context_vk *context_vk)
275 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
276 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
278 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
280 if (!--chunk_vk->c.map_count)
281 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
282 chunk_vk->c.map_ptr = NULL;
285 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
286 unsigned int pool, size_t size)
288 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
289 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
290 VkMemoryAllocateInfo allocate_info;
291 VkDeviceMemory vk_memory;
292 VkResult vr;
294 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
295 allocate_info.pNext = NULL;
296 allocate_info.allocationSize = size;
297 allocate_info.memoryTypeIndex = pool;
298 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
300 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
301 return VK_NULL_HANDLE;
304 return vk_memory;
307 struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
308 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
310 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
311 struct wined3d_allocator *allocator = &device_vk->allocator;
312 struct wined3d_allocator_block *block;
314 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
316 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
317 return NULL;
320 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
322 *vk_memory = VK_NULL_HANDLE;
323 return NULL;
326 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
328 return block;
331 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
332 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
334 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
335 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
336 struct wined3d_bo_slab_vk_key key;
337 struct wined3d_bo_slab_vk *slab;
338 struct wine_rb_entry *entry;
339 size_t object_size, idx;
340 size_t alignment;
342 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
343 return false;
345 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
346 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
347 && limits->minTexelBufferOffsetAlignment > alignment)
348 alignment = limits->minTexelBufferOffsetAlignment;
349 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
350 alignment = limits->minUniformBufferOffsetAlignment;
351 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
352 alignment = limits->minStorageBufferOffsetAlignment;
354 object_size = (size + (alignment - 1)) & ~(alignment - 1);
355 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
356 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
357 key.memory_type = memory_type;
358 key.usage = usage;
359 key.size = 32 * object_size;
361 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
363 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
364 TRACE("Using existing bo slab %p.\n", slab);
366 else
368 if (!(slab = heap_alloc_zero(sizeof(*slab))))
370 ERR("Failed to allocate bo slab.\n");
371 return false;
374 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
376 ERR("Failed to create slab bo.\n");
377 heap_free(slab);
378 return false;
380 slab->map = ~0u;
382 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
384 ERR("Failed to add slab to available tree.\n");
385 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
386 heap_free(slab);
387 return false;
390 TRACE("Created new bo slab %p.\n", slab);
393 idx = wined3d_bit_scan(&slab->map);
394 if (!slab->map)
396 if (slab->next)
398 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
399 slab->next = NULL;
401 else
403 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
407 *bo = slab->bo;
408 bo->memory = NULL;
409 bo->slab = slab;
410 bo->buffer_offset = idx * object_size;
411 bo->memory_offset = slab->bo.memory_offset + bo->buffer_offset;
412 bo->size = size;
413 list_init(&bo->users);
414 bo->command_buffer_id = 0;
416 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
417 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
418 wine_dbgstr_longlong(bo->buffer_offset), bo);
420 return true;
423 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
424 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
426 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
427 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
428 VkMemoryRequirements memory_requirements;
429 struct wined3d_adapter_vk *adapter_vk;
430 VkBufferCreateInfo create_info;
431 unsigned int memory_type_idx;
432 VkResult vr;
434 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
435 return TRUE;
437 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
439 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
440 create_info.pNext = NULL;
441 create_info.flags = 0;
442 create_info.size = size;
443 create_info.usage = usage;
444 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
445 create_info.queueFamilyIndexCount = 0;
446 create_info.pQueueFamilyIndices = NULL;
448 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
450 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
451 return FALSE;
454 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
456 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
457 memory_requirements.memoryTypeBits, memory_type);
458 if (memory_type_idx == ~0u)
460 ERR("Failed to find suitable memory type.\n");
461 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
462 return FALSE;
464 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
465 memory_type_idx, memory_requirements.size, &bo->vk_memory);
466 if (!bo->vk_memory)
468 ERR("Failed to allocate buffer memory.\n");
469 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
470 return FALSE;
472 bo->memory_offset = bo->memory ? bo->memory->offset : 0;
474 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
475 bo->vk_memory, bo->memory_offset))) < 0)
477 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
478 if (bo->memory)
479 wined3d_allocator_block_free(bo->memory);
480 else
481 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
482 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
483 return FALSE;
486 bo->map_ptr = NULL;
487 bo->buffer_offset = 0;
488 bo->size = size;
489 bo->usage = usage;
490 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
491 list_init(&bo->users);
492 bo->command_buffer_id = 0;
493 bo->slab = NULL;
495 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
496 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
498 return TRUE;
501 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
503 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
504 struct wined3d_retired_object_vk *o;
506 if (retired->free)
508 o = retired->free;
509 retired->free = o->u.next;
510 return o;
513 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
514 retired->count + 1, sizeof(*retired->objects)))
515 return NULL;
517 return &retired->objects[retired->count++];
520 void wined3d_context_vk_destroy_framebuffer(struct wined3d_context_vk *context_vk,
521 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
523 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
524 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
525 struct wined3d_retired_object_vk *o;
527 if (context_vk->completed_command_buffer_id > command_buffer_id)
529 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
530 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
531 return;
534 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
536 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
537 return;
540 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
541 o->u.vk_framebuffer = vk_framebuffer;
542 o->command_buffer_id = command_buffer_id;
545 static void wined3d_context_vk_destroy_descriptor_pool(struct wined3d_context_vk *context_vk,
546 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
548 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
549 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
550 struct wined3d_retired_object_vk *o;
552 if (context_vk->completed_command_buffer_id > command_buffer_id)
554 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
555 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
556 return;
559 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
561 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
562 return;
565 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
566 o->u.vk_descriptor_pool = vk_descriptor_pool;
567 o->command_buffer_id = command_buffer_id;
570 void wined3d_context_vk_destroy_memory(struct wined3d_context_vk *context_vk,
571 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
573 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
574 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
575 struct wined3d_retired_object_vk *o;
577 if (context_vk->completed_command_buffer_id > command_buffer_id)
579 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
580 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
581 return;
584 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
586 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
587 return;
590 o->type = WINED3D_RETIRED_MEMORY_VK;
591 o->u.vk_memory = vk_memory;
592 o->command_buffer_id = command_buffer_id;
595 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
596 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
598 struct wined3d_retired_object_vk *o;
600 if (context_vk->completed_command_buffer_id > command_buffer_id)
602 wined3d_allocator_block_free(block);
603 TRACE("Freed block %p.\n", block);
604 return;
607 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
609 ERR("Leaking block %p.\n", block);
610 return;
613 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
614 o->u.block = block;
615 o->command_buffer_id = command_buffer_id;
618 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
619 SIZE_T idx, struct wined3d_context_vk *context_vk)
621 struct wined3d_bo_slab_vk_key key;
622 struct wine_rb_entry *entry;
624 TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
626 if (!slab->map)
628 key.memory_type = slab->bo.memory_type;
629 key.usage = slab->bo.usage;
630 key.size = slab->bo.size;
632 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
634 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
635 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
637 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
639 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
642 slab->map |= 1u << idx;
645 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
646 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
648 struct wined3d_retired_object_vk *o;
650 if (context_vk->completed_command_buffer_id > command_buffer_id)
652 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
653 return;
656 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
658 ERR("Leaking slab %p, slice %#lx.\n", slab, idx);
659 return;
662 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
663 o->u.slice.slab = slab;
664 o->u.slice.idx = idx;
665 o->command_buffer_id = command_buffer_id;
668 static void wined3d_context_vk_destroy_buffer(struct wined3d_context_vk *context_vk,
669 VkBuffer vk_buffer, uint64_t command_buffer_id)
671 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
672 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
673 struct wined3d_retired_object_vk *o;
675 if (context_vk->completed_command_buffer_id > command_buffer_id)
677 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
678 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
679 return;
682 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
684 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
685 return;
688 o->type = WINED3D_RETIRED_BUFFER_VK;
689 o->u.vk_buffer = vk_buffer;
690 o->command_buffer_id = command_buffer_id;
693 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk,
694 VkImage vk_image, uint64_t command_buffer_id)
696 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
697 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
698 struct wined3d_retired_object_vk *o;
700 if (context_vk->completed_command_buffer_id > command_buffer_id)
702 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
703 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
704 return;
707 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
709 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
710 return;
713 o->type = WINED3D_RETIRED_IMAGE_VK;
714 o->u.vk_image = vk_image;
715 o->command_buffer_id = command_buffer_id;
718 void wined3d_context_vk_destroy_buffer_view(struct wined3d_context_vk *context_vk,
719 VkBufferView vk_view, uint64_t command_buffer_id)
721 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
722 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
723 struct wined3d_retired_object_vk *o;
725 if (context_vk->completed_command_buffer_id > command_buffer_id)
727 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
728 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
729 return;
732 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
734 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
735 return;
738 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
739 o->u.vk_buffer_view = vk_view;
740 o->command_buffer_id = command_buffer_id;
743 void wined3d_context_vk_destroy_image_view(struct wined3d_context_vk *context_vk,
744 VkImageView vk_view, uint64_t command_buffer_id)
746 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
747 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
748 struct wined3d_retired_object_vk *o;
750 if (context_vk->completed_command_buffer_id > command_buffer_id)
752 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
753 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
754 return;
757 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
759 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
760 return;
763 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
764 o->u.vk_image_view = vk_view;
765 o->command_buffer_id = command_buffer_id;
768 void wined3d_context_vk_destroy_sampler(struct wined3d_context_vk *context_vk,
769 VkSampler vk_sampler, uint64_t command_buffer_id)
771 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
772 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
773 struct wined3d_retired_object_vk *o;
775 if (context_vk->completed_command_buffer_id > command_buffer_id)
777 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
778 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
779 return;
782 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
784 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
785 return;
788 o->type = WINED3D_RETIRED_SAMPLER_VK;
789 o->u.vk_sampler = vk_sampler;
790 o->command_buffer_id = command_buffer_id;
793 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
795 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
796 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
797 size_t object_size, idx;
799 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
801 if (bo->slab)
803 object_size = bo->slab->bo.size / 32;
804 idx = bo->buffer_offset / object_size;
805 wined3d_context_vk_destroy_bo_slab_slice(context_vk, bo->slab, idx, bo->command_buffer_id);
806 return;
809 wined3d_context_vk_destroy_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
810 if (bo->memory)
812 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
813 return;
816 if (bo->map_ptr)
817 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
818 wined3d_context_vk_destroy_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
821 void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk)
823 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
824 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
825 struct wined3d_command_buffer_vk *buffer;
826 SIZE_T i = 0;
828 while (i < context_vk->submitted.buffer_count)
830 buffer = &context_vk->submitted.buffers[i];
831 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
833 ++i;
834 continue;
837 TRACE("Command buffer %p with id 0x%s has finished.\n",
838 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
839 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
840 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
841 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
843 if (buffer->id > context_vk->completed_command_buffer_id)
844 context_vk->completed_command_buffer_id = buffer->id;
845 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
849 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk)
851 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
852 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
853 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
854 struct wined3d_retired_object_vk *o;
855 uint64_t command_buffer_id;
856 SIZE_T i = 0;
858 wined3d_context_vk_poll_command_buffers(context_vk);
859 command_buffer_id = context_vk->completed_command_buffer_id;
861 retired->free = NULL;
862 for (i = retired->count; i; --i)
864 o = &retired->objects[i - 1];
866 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
867 continue;
869 switch (o->type)
871 case WINED3D_RETIRED_FREE_VK:
872 /* Nothing to do. */
873 break;
875 case WINED3D_RETIRED_FRAMEBUFFER_VK:
876 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
877 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
878 break;
880 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
881 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, o->u.vk_descriptor_pool, NULL));
882 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
883 break;
885 case WINED3D_RETIRED_MEMORY_VK:
886 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
887 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
888 break;
890 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
891 TRACE("Destroying block %p.\n", o->u.block);
892 wined3d_allocator_block_free(o->u.block);
893 break;
895 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
896 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
897 break;
899 case WINED3D_RETIRED_BUFFER_VK:
900 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
901 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
902 break;
904 case WINED3D_RETIRED_IMAGE_VK:
905 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
906 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
907 break;
909 case WINED3D_RETIRED_BUFFER_VIEW_VK:
910 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
911 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
912 break;
914 case WINED3D_RETIRED_IMAGE_VIEW_VK:
915 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
916 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
917 break;
919 case WINED3D_RETIRED_SAMPLER_VK:
920 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
921 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
922 break;
924 default:
925 ERR("Unhandled object type %#x.\n", o->type);
926 break;
929 if (i == retired->count)
931 --retired->count;
932 continue;
935 o->type = WINED3D_RETIRED_FREE_VK;
936 o->u.next = retired->free;
937 retired->free = o;
941 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
943 struct wined3d_context_vk *context_vk = ctx;
944 struct wined3d_bo_slab_vk *slab, *next;
946 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
947 while (slab)
949 next = slab->next;
950 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
951 heap_free(slab);
952 slab = next;
956 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
958 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
959 struct wined3d_graphics_pipeline_vk, entry);
960 struct wined3d_context_vk *context_vk = ctx;
961 const struct wined3d_vk_info *vk_info;
962 struct wined3d_device_vk *device_vk;
964 vk_info = context_vk->vk_info;
965 device_vk = wined3d_device_vk(context_vk->c.device);
967 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
968 heap_free(pipeline_vk);
971 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
973 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
974 struct wined3d_pipeline_layout_vk, entry);
975 struct wined3d_context_vk *context_vk = ctx;
976 const struct wined3d_vk_info *vk_info;
977 struct wined3d_device_vk *device_vk;
979 vk_info = context_vk->vk_info;
980 device_vk = wined3d_device_vk(context_vk->c.device);
982 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
983 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
984 heap_free(layout->key.bindings);
985 heap_free(layout);
988 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
989 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
991 struct wined3d_render_pass_attachment_vk *a;
992 struct wined3d_rendertarget_view *view;
993 unsigned int i;
995 memset(key, 0, sizeof(*key));
997 for (i = 0; i < rt_count; ++i)
999 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1000 continue;
1002 a = &key->rt[i];
1003 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1004 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1005 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1006 key->rt_mask |= 1u << i;
1009 if (depth_stencil && (view = fb->depth_stencil))
1011 a = &key->ds;
1012 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1013 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1014 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1015 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1018 key->clear_flags = clear_flags;
1021 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1022 struct wined3d_context_vk *context_vk)
1024 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1025 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1027 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1030 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1031 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1033 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1034 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1035 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1036 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1037 const struct wined3d_render_pass_attachment_vk *a;
1038 VkAttachmentReference ds_attachment_reference;
1039 VkAttachmentReference *ds_reference = NULL;
1040 unsigned int attachment_count, rt_count, i;
1041 VkAttachmentDescription *attachment;
1042 VkSubpassDescription sub_pass_desc;
1043 VkRenderPassCreateInfo pass_desc;
1044 uint32_t mask;
1045 VkResult vr;
1047 rt_count = 0;
1048 attachment_count = 0;
1049 mask = key->rt_mask & ((1u << WINED3D_MAX_RENDER_TARGETS) - 1);
1050 while (mask)
1052 i = wined3d_bit_scan(&mask);
1053 a = &key->rt[i];
1055 attachment = &attachments[attachment_count];
1056 attachment->flags = 0;
1057 attachment->format = a->vk_format;
1058 attachment->samples = a->vk_samples;
1059 if (key->clear_flags & WINED3DCLEAR_TARGET)
1060 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1061 else
1062 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1063 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1064 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1065 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1066 attachment->initialLayout = a->vk_layout;
1067 attachment->finalLayout = a->vk_layout;
1069 attachment_references[i].attachment = attachment_count;
1070 attachment_references[i].layout = a->vk_layout;
1072 ++attachment_count;
1073 rt_count = i + 1;
1076 mask = ~key->rt_mask & ((1u << rt_count) - 1);
1077 while (mask)
1079 i = wined3d_bit_scan(&mask);
1080 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1081 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1084 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1086 a = &key->ds;
1088 attachment = &attachments[attachment_count];
1089 attachment->flags = 0;
1090 attachment->format = a->vk_format;
1091 attachment->samples = a->vk_samples;
1092 if (key->clear_flags & WINED3DCLEAR_ZBUFFER)
1093 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1094 else
1095 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1096 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1097 if (key->clear_flags & WINED3DCLEAR_STENCIL)
1098 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1099 else
1100 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1101 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1102 attachment->initialLayout = a->vk_layout;
1103 attachment->finalLayout = a->vk_layout;
1105 ds_reference = &ds_attachment_reference;
1106 ds_reference->attachment = attachment_count;
1107 ds_reference->layout = a->vk_layout;
1109 ++attachment_count;
1112 sub_pass_desc.flags = 0;
1113 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1114 sub_pass_desc.inputAttachmentCount = 0;
1115 sub_pass_desc.pInputAttachments = NULL;
1116 sub_pass_desc.colorAttachmentCount = rt_count;
1117 sub_pass_desc.pColorAttachments = attachment_references;
1118 sub_pass_desc.pResolveAttachments = NULL;
1119 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1120 sub_pass_desc.preserveAttachmentCount = 0;
1121 sub_pass_desc.pPreserveAttachments = NULL;
1123 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1124 pass_desc.pNext = NULL;
1125 pass_desc.flags = 0;
1126 pass_desc.attachmentCount = attachment_count;
1127 pass_desc.pAttachments = attachments;
1128 pass_desc.subpassCount = 1;
1129 pass_desc.pSubpasses = &sub_pass_desc;
1130 pass_desc.dependencyCount = 0;
1131 pass_desc.pDependencies = NULL;
1133 pass->key = *key;
1134 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1135 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1137 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1138 return false;
1141 return true;
1144 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1145 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1147 struct wined3d_render_pass_key_vk key;
1148 struct wined3d_render_pass_vk *pass;
1149 struct wine_rb_entry *entry;
1151 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1152 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1153 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1155 if (!(pass = heap_alloc(sizeof(*pass))))
1156 return VK_NULL_HANDLE;
1158 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1160 heap_free(pass);
1161 return VK_NULL_HANDLE;
1164 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1166 ERR("Failed to insert render pass.\n");
1167 wined3d_render_pass_vk_cleanup(pass, context_vk);
1168 heap_free(pass);
1169 return VK_NULL_HANDLE;
1172 return pass->vk_render_pass;
1175 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1177 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1178 VkCommandBuffer vk_command_buffer;
1180 if (context_vk->vk_render_pass)
1182 vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1183 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1184 context_vk->vk_render_pass = VK_NULL_HANDLE;
1185 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1186 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1189 if (context_vk->vk_framebuffer)
1191 wined3d_context_vk_destroy_framebuffer(context_vk,
1192 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1193 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1197 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1199 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1200 struct wined3d_render_pass_vk, entry);
1202 wined3d_render_pass_vk_cleanup(pass, ctx);
1203 heap_free(pass);
1206 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1208 heap_free(writes->writes);
1211 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1213 struct wined3d_query_pool_vk *pool_vk, *entry;
1215 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1217 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1218 heap_free(pool_vk);
1222 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1223 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1225 struct wined3d_query_pool_vk *pool_vk, *entry;
1226 struct list *free_pools;
1227 size_t idx;
1229 switch (type)
1231 case WINED3D_QUERY_TYPE_OCCLUSION:
1232 free_pools = &context_vk->free_occlusion_query_pools;
1233 break;
1235 case WINED3D_QUERY_TYPE_TIMESTAMP:
1236 free_pools = &context_vk->free_timestamp_query_pools;
1237 break;
1239 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1240 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1241 break;
1243 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1244 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1245 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1246 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1247 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1248 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1249 break;
1251 default:
1252 FIXME("Unhandled query type %#x.\n", type);
1253 return false;
1256 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1258 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1259 goto done;
1260 list_remove(&pool_vk->entry);
1263 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1264 return false;
1265 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1267 heap_free(pool_vk);
1268 return false;
1271 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1273 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1274 heap_free(pool_vk);
1275 return false;
1278 done:
1279 pool_idx->pool_vk = pool_vk;
1280 pool_idx->idx = idx;
1282 return true;
1285 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1287 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1288 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1289 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1291 if (buffer->vk_command_buffer)
1293 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1294 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1295 buffer->vk_command_buffer = VK_NULL_HANDLE;
1298 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1299 context_vk->completed_command_buffer_id = buffer->id;
1301 heap_free(context_vk->compute.bindings.bindings);
1302 heap_free(context_vk->graphics.bindings.bindings);
1303 if (context_vk->vk_descriptor_pool)
1304 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pool, NULL));
1305 if (context_vk->vk_framebuffer)
1306 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1307 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1308 if (context_vk->vk_so_counter_bo.vk_buffer)
1309 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1310 wined3d_context_vk_cleanup_resources(context_vk);
1311 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1312 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1313 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1314 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1315 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1316 heap_free(context_vk->pending_queries.queries);
1317 heap_free(context_vk->submitted.buffers);
1318 heap_free(context_vk->retired.objects);
1320 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1321 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1322 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1323 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1325 wined3d_context_cleanup(&context_vk->c);
1328 void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *context_vk,
1329 struct wined3d_query_vk *query_vk)
1331 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1332 struct wined3d_pending_query_vk *p;
1333 size_t i;
1335 pending->free_idx = ~(size_t)0;
1336 for (i = pending->count; i; --i)
1338 p = &pending->queries[i - 1];
1340 if (p->query_vk)
1342 if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx))
1343 continue;
1344 wined3d_query_pool_vk_free_query(p->pool_idx.pool_vk, p->pool_idx.idx);
1345 --p->query_vk->pending_count;
1348 if (i == pending->count)
1350 --pending->count;
1351 continue;
1354 p->query_vk = NULL;
1355 p->pool_idx.pool_vk = NULL;
1356 p->pool_idx.idx = pending->free_idx;
1357 pending->free_idx = i - 1;
1361 void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk *context_vk)
1363 wined3d_context_vk_remove_pending_queries(context_vk, NULL);
1366 void wined3d_context_vk_add_pending_query(struct wined3d_context_vk *context_vk, struct wined3d_query_vk *query_vk)
1368 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1369 struct wined3d_pending_query_vk *p;
1371 if (pending->free_idx != ~(size_t)0)
1373 p = &pending->queries[pending->free_idx];
1374 pending->free_idx = p->pool_idx.idx;
1376 else
1378 if (!wined3d_array_reserve((void **)&pending->queries, &pending->size,
1379 pending->count + 1, sizeof(*pending->queries)))
1381 ERR("Failed to allocate entry.\n");
1382 return;
1384 p = &pending->queries[pending->count++];
1387 p->query_vk = query_vk;
1388 p->pool_idx = query_vk->pool_idx;
1389 ++query_vk->pending_count;
1392 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1394 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1395 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1396 VkCommandBufferAllocateInfo command_buffer_info;
1397 struct wined3d_command_buffer_vk *buffer;
1398 VkCommandBufferBeginInfo begin_info;
1399 struct wined3d_query_vk *query_vk;
1400 VkResult vr;
1402 TRACE("context_vk %p.\n", context_vk);
1404 buffer = &context_vk->current_command_buffer;
1405 if (buffer->vk_command_buffer)
1407 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1408 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1409 return buffer->vk_command_buffer;
1412 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1413 command_buffer_info.pNext = NULL;
1414 command_buffer_info.commandPool = context_vk->vk_command_pool;
1415 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1416 command_buffer_info.commandBufferCount = 1;
1417 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1418 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1420 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1421 return VK_NULL_HANDLE;
1424 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1425 begin_info.pNext = NULL;
1426 begin_info.flags = 0;
1427 begin_info.pInheritanceInfo = NULL;
1428 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1430 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1431 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1432 1, &buffer->vk_command_buffer));
1433 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1436 wined3d_context_vk_accumulate_pending_queries(context_vk);
1437 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1439 wined3d_query_vk_resume(query_vk, context_vk);
1442 TRACE("Created new command buffer %p with id 0x%s.\n",
1443 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1445 return buffer->vk_command_buffer;
1448 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1449 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1450 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1452 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1453 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1454 struct wined3d_command_buffer_vk *buffer;
1455 struct wined3d_query_vk *query_vk;
1456 VkFenceCreateInfo fence_desc;
1457 VkSubmitInfo submit_info;
1458 VkResult vr;
1460 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1461 "signal_semaphore_count %u, signal_semaphores %p.\n",
1462 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1463 signal_semaphore_count, signal_semaphores);
1465 buffer = &context_vk->current_command_buffer;
1466 if (!buffer->vk_command_buffer)
1467 return;
1469 TRACE("Submitting command buffer %p with id 0x%s.\n",
1470 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1472 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1474 wined3d_query_vk_suspend(query_vk, context_vk);
1477 wined3d_context_vk_end_current_render_pass(context_vk);
1478 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1479 context_vk->update_compute_pipeline = 1;
1480 context_vk->update_stream_output = 1;
1481 context_vk->c.update_shader_resource_bindings = 1;
1482 context_vk->c.update_compute_shader_resource_bindings = 1;
1483 context_vk->c.update_unordered_access_view_bindings = 1;
1484 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1485 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1486 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1487 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1489 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1491 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1492 fence_desc.pNext = NULL;
1493 fence_desc.flags = 0;
1494 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1495 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1497 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1498 submit_info.pNext = NULL;
1499 submit_info.waitSemaphoreCount = wait_semaphore_count;
1500 submit_info.pWaitSemaphores = wait_semaphores;
1501 submit_info.pWaitDstStageMask = wait_stages;
1502 submit_info.commandBufferCount = 1;
1503 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1504 submit_info.signalSemaphoreCount = signal_semaphore_count;
1505 submit_info.pSignalSemaphores = signal_semaphores;
1507 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1508 ERR("Failed to submit command buffer %p, vr %s.\n",
1509 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1511 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1512 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1513 ERR("Failed to grow submitted command buffer array.\n");
1515 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1517 buffer->vk_command_buffer = VK_NULL_HANDLE;
1518 /* We don't expect this to ever happen, but handle it anyway. */
1519 if (!++buffer->id)
1521 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1522 context_vk->completed_command_buffer_id = 0;
1523 buffer->id = 1;
1525 wined3d_context_vk_cleanup_resources(context_vk);
1528 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1530 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1531 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1532 SIZE_T i;
1534 if (id <= context_vk->completed_command_buffer_id
1535 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1536 return;
1538 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1540 if (context_vk->submitted.buffers[i].id != id)
1541 continue;
1543 VK_CALL(vkWaitForFences(device_vk->vk_device, 1,
1544 &context_vk->submitted.buffers[i].vk_fence, VK_TRUE, UINT64_MAX));
1545 wined3d_context_vk_cleanup_resources(context_vk);
1546 return;
1549 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1552 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1553 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1554 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1555 VkImageLayout new_layout, VkImage image, VkImageAspectFlags aspect_mask)
1557 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1558 VkImageMemoryBarrier barrier;
1560 wined3d_context_vk_end_current_render_pass(context_vk);
1562 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1563 barrier.pNext = NULL;
1564 barrier.srcAccessMask = src_access_mask;
1565 barrier.dstAccessMask = dst_access_mask;
1566 barrier.oldLayout = old_layout;
1567 barrier.newLayout = new_layout;
1568 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1569 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1570 barrier.image = image;
1571 barrier.subresourceRange.aspectMask = aspect_mask;
1572 barrier.subresourceRange.baseMipLevel = 0;
1573 barrier.subresourceRange.levelCount = VK_REMAINING_MIP_LEVELS;
1574 barrier.subresourceRange.baseArrayLayer = 0;
1575 barrier.subresourceRange.layerCount = VK_REMAINING_ARRAY_LAYERS;
1577 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1580 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1582 const struct wined3d_render_pass_key_vk *k = key;
1583 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1584 const struct wined3d_render_pass_vk, entry);
1586 return memcmp(k, &pass->key, sizeof(*k));
1589 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1591 const struct wined3d_pipeline_layout_key_vk *a = key;
1592 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1593 const struct wined3d_pipeline_layout_vk, entry)->key;
1595 if (a->binding_count != b->binding_count)
1596 return a->binding_count - b->binding_count;
1597 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1600 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1602 const struct wined3d_graphics_pipeline_key_vk *a = key;
1603 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1604 const struct wined3d_graphics_pipeline_vk, entry)->key;
1605 unsigned int i;
1606 int ret;
1608 if (a->pipeline_desc.stageCount != b->pipeline_desc.stageCount)
1609 return a->pipeline_desc.stageCount - b->pipeline_desc.stageCount;
1610 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1612 if (a->stages[i].module != b->stages[i].module)
1613 return a->stages[i].module - b->stages[i].module;
1616 if (a->divisor_desc.vertexBindingDivisorCount != b->divisor_desc.vertexBindingDivisorCount)
1617 return a->divisor_desc.vertexBindingDivisorCount - b->divisor_desc.vertexBindingDivisorCount;
1618 if ((ret = memcmp(a->divisors, b->divisors,
1619 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1620 return ret;
1622 if (a->input_desc.vertexAttributeDescriptionCount != b->input_desc.vertexAttributeDescriptionCount)
1623 return a->input_desc.vertexAttributeDescriptionCount - b->input_desc.vertexAttributeDescriptionCount;
1624 if ((ret = memcmp(a->attributes, b->attributes,
1625 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1626 return ret;
1627 if (a->input_desc.vertexBindingDescriptionCount != b->input_desc.vertexBindingDescriptionCount)
1628 return a->input_desc.vertexBindingDescriptionCount - b->input_desc.vertexBindingDescriptionCount;
1629 if ((ret = memcmp(a->bindings, b->bindings,
1630 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1631 return ret;
1633 if (a->ia_desc.topology != b->ia_desc.topology)
1634 return a->ia_desc.topology - b->ia_desc.topology;
1635 if (a->ia_desc.primitiveRestartEnable != b->ia_desc.primitiveRestartEnable)
1636 return a->ia_desc.primitiveRestartEnable - b->ia_desc.primitiveRestartEnable;
1638 if (a->ts_desc.patchControlPoints != b->ts_desc.patchControlPoints)
1639 return a->ts_desc.patchControlPoints - b->ts_desc.patchControlPoints;
1641 if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport))))
1642 return ret;
1644 if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor))))
1645 return ret;
1647 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
1648 return ret;
1650 if (a->ms_desc.rasterizationSamples != b->ms_desc.rasterizationSamples)
1651 return a->ms_desc.rasterizationSamples - b->ms_desc.rasterizationSamples;
1652 if (a->ms_desc.alphaToCoverageEnable != b->ms_desc.alphaToCoverageEnable)
1653 return a->ms_desc.alphaToCoverageEnable - b->ms_desc.alphaToCoverageEnable;
1654 if (a->sample_mask != b->sample_mask)
1655 return a->sample_mask - b->sample_mask;
1657 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
1658 return ret;
1660 if (a->blend_desc.attachmentCount != b->blend_desc.attachmentCount)
1661 return a->blend_desc.attachmentCount - b->blend_desc.attachmentCount;
1662 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
1663 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
1664 return ret;
1666 if (a->pipeline_desc.layout != b->pipeline_desc.layout)
1667 return a->pipeline_desc.layout - b->pipeline_desc.layout;
1669 if (a->pipeline_desc.renderPass != b->pipeline_desc.renderPass)
1670 return a->pipeline_desc.renderPass - b->pipeline_desc.renderPass;
1672 return 0;
1675 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
1677 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
1678 const struct wined3d_bo_slab_vk_key *k = key;
1680 if (k->memory_type != slab->bo.memory_type)
1681 return k->memory_type - slab->bo.memory_type;
1682 if (k->usage != slab->bo.usage)
1683 return k->usage - slab->bo.usage;
1684 return k->size - slab->bo.size;
1687 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
1689 struct wined3d_graphics_pipeline_key_vk *key;
1690 VkPipelineShaderStageCreateInfo *stage;
1691 unsigned int i;
1693 static const VkDynamicState dynamic_states[] =
1695 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1698 key = &context_vk->graphics.pipeline_key_vk;
1699 memset(key, 0, sizeof(*key));
1701 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
1703 stage = &key->stages[i];
1704 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1705 stage->pName = "main";
1708 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1709 key->input_desc.pVertexBindingDescriptions = key->bindings;
1710 key->input_desc.pVertexAttributeDescriptions = key->attributes;
1712 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1713 key->divisor_desc.pVertexBindingDivisors = key->divisors;
1715 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1717 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1719 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1720 key->vp_desc.viewportCount = 1;
1721 key->vp_desc.pViewports = &key->viewport;
1722 key->vp_desc.scissorCount = 1;
1723 key->vp_desc.pScissors = &key->scissor;
1725 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1726 key->rs_desc.lineWidth = 1.0f;
1728 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1729 key->ms_desc.pSampleMask = &key->sample_mask;
1731 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1732 key->ds_desc.maxDepthBounds = 1.0f;
1734 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1735 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
1736 key->blend_desc.pAttachments = key->blend_attachments;
1737 key->blend_desc.blendConstants[0] = 1.0f;
1738 key->blend_desc.blendConstants[1] = 1.0f;
1739 key->blend_desc.blendConstants[2] = 1.0f;
1740 key->blend_desc.blendConstants[3] = 1.0f;
1742 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1743 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
1744 key->dynamic_desc.pDynamicStates = dynamic_states;
1746 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1747 key->pipeline_desc.pStages = key->stages;
1748 key->pipeline_desc.pVertexInputState = &key->input_desc;
1749 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
1750 key->pipeline_desc.pTessellationState = &key->ts_desc;
1751 key->pipeline_desc.pViewportState = &key->vp_desc;
1752 key->pipeline_desc.pRasterizationState = &key->rs_desc;
1753 key->pipeline_desc.pMultisampleState = &key->ms_desc;
1754 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
1755 key->pipeline_desc.pColorBlendState = &key->blend_desc;
1756 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
1757 key->pipeline_desc.basePipelineIndex = -1;
1760 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
1761 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1763 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
1764 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
1765 const struct wined3d_rasterizer_state_desc *r;
1766 float scale_bias;
1767 union
1769 uint32_t u32;
1770 float f32;
1771 } const_bias;
1773 if (!state->rasterizer_state)
1775 desc->depthClampEnable = VK_FALSE;
1776 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1777 desc->cullMode = VK_CULL_MODE_BACK_BIT;
1778 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
1779 desc->depthBiasEnable = VK_FALSE;
1780 desc->depthBiasConstantFactor = 0.0f;
1781 desc->depthBiasClamp = 0.0f;
1782 desc->depthBiasSlopeFactor = 0.0f;
1784 return;
1787 r = &state->rasterizer_state->desc;
1788 desc->depthClampEnable = !r->depth_clip;
1789 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1790 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
1791 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
1793 scale_bias = r->scale_bias;
1794 const_bias.f32 = r->depth_bias;
1795 if (!scale_bias && !const_bias.f32)
1797 desc->depthBiasEnable = VK_FALSE;
1798 desc->depthBiasConstantFactor = 0.0f;
1799 desc->depthBiasClamp = 0.0f;
1800 desc->depthBiasSlopeFactor = 0.0f;
1802 return;
1805 desc->depthBiasEnable = VK_TRUE;
1806 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
1808 const struct wined3d_rendertarget_view *dsv;
1810 if ((dsv = state->fb.depth_stencil))
1812 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
1813 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
1815 else
1817 desc->depthBiasConstantFactor = 0.0f;
1818 desc->depthBiasSlopeFactor = 0.0f;
1821 else
1823 desc->depthBiasConstantFactor = const_bias.f32;
1824 desc->depthBiasSlopeFactor = scale_bias;
1826 desc->depthBiasClamp = r->depth_bias_clamp;
1829 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
1830 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1832 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
1833 const struct wined3d_blend_state_desc *b;
1834 unsigned int i;
1836 desc->attachmentCount = context_vk->rt_count;
1838 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
1839 if (!state->blend_state)
1841 for (i = 0; i < context_vk->rt_count; ++i)
1843 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
1844 | VK_COLOR_COMPONENT_G_BIT
1845 | VK_COLOR_COMPONENT_B_BIT
1846 | VK_COLOR_COMPONENT_A_BIT;
1849 return;
1852 b = &state->blend_state->desc;
1853 for (i = 0; i < context_vk->rt_count; ++i)
1855 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
1856 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
1857 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
1858 enum wined3d_blend src_blend, dst_blend;
1859 const struct wined3d_format *rt_format;
1861 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
1862 if (!rt->enable)
1863 continue;
1865 if (rtv)
1866 rt_format = rtv->format;
1867 else
1868 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
1869 a->blendEnable = VK_TRUE;
1871 src_blend = rt->src;
1872 dst_blend = rt->dst;
1873 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
1875 src_blend = WINED3D_BLEND_SRCALPHA;
1876 dst_blend = WINED3D_BLEND_INVSRCALPHA;
1878 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
1880 src_blend = WINED3D_BLEND_INVSRCALPHA;
1881 dst_blend = WINED3D_BLEND_SRCALPHA;
1883 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
1884 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
1885 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
1887 src_blend = rt->src_alpha;
1888 dst_blend = rt->dst_alpha;
1889 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
1890 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
1891 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
1895 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
1896 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout)
1898 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
1899 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
1900 struct wined3d_graphics_pipeline_key_vk *key;
1901 VkPipelineShaderStageCreateInfo *stage;
1902 struct wined3d_stream_info stream_info;
1903 VkPrimitiveTopology vk_topology;
1904 VkShaderModule module;
1905 bool update = false;
1906 uint32_t mask;
1908 key = &context_vk->graphics.pipeline_key_vk;
1910 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
1912 stage_count = 0;
1913 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
1915 if (!(module = context_vk->graphics.vk_modules[i]))
1916 continue;
1918 stage = &key->stages[stage_count++];
1919 stage->stage = vk_shader_stage_from_wined3d(i);
1920 stage->module = module;
1923 key->pipeline_desc.stageCount = stage_count;
1925 update = true;
1928 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
1929 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
1930 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
1932 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
1933 divisor_count = 0;
1934 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
1936 VkVertexInputBindingDivisorDescriptionEXT *d;
1937 struct wined3d_stream_info_element *e;
1938 VkVertexInputAttributeDescription *a;
1939 VkVertexInputBindingDescription *b;
1940 uint32_t binding;
1942 if (!(stream_info.use_map & (1u << i)))
1943 continue;
1945 a = &key->attributes[attribute_count++];
1946 e = &stream_info.elements[i];
1947 binding = e->stream_idx;
1949 a->location = i;
1950 a->binding = binding;
1951 a->format = wined3d_format_vk(e->format)->vk_format;
1952 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
1954 if (mask & (1u << binding))
1955 continue;
1956 mask |= 1u << binding;
1958 b = &key->bindings[binding_count++];
1959 b->binding = binding;
1960 b->stride = e->stride;
1961 b->inputRate = e->divisor ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
1963 if (e->divisor > 1)
1965 d = &key->divisors[divisor_count++];
1966 d->binding = binding;
1967 d->divisor = e->divisor;
1971 key->input_desc.pNext = NULL;
1972 key->input_desc.vertexBindingDescriptionCount = binding_count;
1973 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
1975 if (divisor_count)
1977 key->input_desc.pNext = &key->divisor_desc;
1978 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
1981 update = true;
1984 vk_topology = vk_topology_from_wined3d(state->primitive_type);
1985 if (key->ia_desc.topology != vk_topology)
1987 key->ia_desc.topology = vk_topology;
1988 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
1989 && !wined3d_primitive_type_is_list(state->primitive_type);
1991 update = true;
1994 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
1996 key->ts_desc.patchControlPoints = state->patch_vertex_count;
1998 update = true;
2001 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2002 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2003 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2005 key->viewport.x = state->viewports[0].x;
2006 key->viewport.y = state->viewports[0].y;
2007 key->viewport.width = state->viewports[0].width;
2008 key->viewport.height = state->viewports[0].height;
2009 key->viewport.minDepth = state->viewports[0].min_z;
2010 key->viewport.maxDepth = state->viewports[0].max_z;
2012 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2014 const RECT *r = &state->scissor_rects[0];
2016 key->scissor.offset.x = r->left;
2017 key->scissor.offset.y = r->top;
2018 key->scissor.extent.width = r->right - r->left;
2019 key->scissor.extent.height = r->bottom - r->top;
2021 else
2023 key->scissor.offset.x = key->viewport.x;
2024 key->scissor.offset.y = key->viewport.y;
2025 key->scissor.extent.width = key->viewport.width;
2026 key->scissor.extent.height = key->viewport.height;
2028 key->viewport.y += key->viewport.height;
2029 key->viewport.height = -key->viewport.height;
2031 update = true;
2034 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2035 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2037 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2039 update = true;
2042 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2043 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2045 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2046 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2047 key->sample_mask = state->sample_mask;
2049 update = true;
2052 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2053 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2055 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2057 if (d)
2059 key->ds_desc.depthTestEnable = d->desc.depth;
2060 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2061 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2062 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2063 if (key->ds_desc.stencilTestEnable)
2065 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2066 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2067 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2068 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2069 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2070 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2071 key->ds_desc.front.reference = state->render_states[WINED3D_RS_STENCILREF]
2072 & ((1 << state->fb.depth_stencil->format->stencil_size) - 1);
2074 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2075 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2076 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2077 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2078 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2079 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2080 key->ds_desc.back.reference = state->render_states[WINED3D_RS_STENCILREF]
2081 & ((1 << state->fb.depth_stencil->format->stencil_size) - 1);
2083 else
2085 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2086 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2089 else
2091 key->ds_desc.depthTestEnable = VK_TRUE;
2092 key->ds_desc.depthWriteEnable = VK_TRUE;
2093 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2094 key->ds_desc.stencilTestEnable = VK_FALSE;
2097 update = true;
2100 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2101 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2103 wined3d_context_vk_update_blend_state(context_vk, state, key);
2105 update = true;
2108 if (key->pipeline_desc.layout != vk_pipeline_layout)
2110 key->pipeline_desc.layout = vk_pipeline_layout;
2112 update = true;
2115 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2117 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2119 update = true;
2122 return update;
2125 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2126 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2128 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2129 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2130 unsigned int fb_width, fb_height, fb_layer_count;
2131 struct wined3d_rendertarget_view_vk *rtv_vk;
2132 struct wined3d_rendertarget_view *view;
2133 const VkPhysicalDeviceLimits *limits;
2134 VkRenderPassBeginInfo begin_info;
2135 unsigned int attachment_count, i;
2136 VkFramebufferCreateInfo fb_desc;
2137 VkResult vr;
2139 if (context_vk->vk_render_pass)
2140 return true;
2142 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2143 fb_width = limits->maxFramebufferWidth;
2144 fb_height = limits->maxFramebufferHeight;
2145 fb_layer_count = limits->maxFramebufferLayers;
2146 attachment_count = 0;
2148 context_vk->rt_count = 0;
2149 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2151 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2152 continue;
2154 rtv_vk = wined3d_rendertarget_view_vk(view);
2155 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2156 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2158 if (view->width < fb_width)
2159 fb_width = view->width;
2160 if (view->height < fb_height)
2161 fb_height = view->height;
2162 if (view->layer_count < fb_layer_count)
2163 fb_layer_count = view->layer_count;
2164 context_vk->rt_count = i + 1;
2165 ++attachment_count;
2168 if (wined3d_state_uses_depth_buffer(state) && (view = state->fb.depth_stencil))
2170 rtv_vk = wined3d_rendertarget_view_vk(view);
2171 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2172 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2174 if (view->width < fb_width)
2175 fb_width = view->width;
2176 if (view->height < fb_height)
2177 fb_height = view->height;
2178 if (view->layer_count < fb_layer_count)
2179 fb_layer_count = view->layer_count;
2180 ++attachment_count;
2183 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2184 ARRAY_SIZE(state->fb.render_targets), wined3d_state_uses_depth_buffer(state), 0)))
2186 ERR("Failed to get render pass.\n");
2187 return false;
2190 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2191 fb_desc.pNext = NULL;
2192 fb_desc.flags = 0;
2193 fb_desc.renderPass = context_vk->vk_render_pass;
2194 fb_desc.attachmentCount = attachment_count;
2195 fb_desc.pAttachments = vk_views;
2196 fb_desc.width = fb_width;
2197 fb_desc.height = fb_height;
2198 fb_desc.layers = fb_layer_count;
2200 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2202 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2203 return false;
2206 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2207 begin_info.pNext = NULL;
2208 begin_info.renderPass = context_vk->vk_render_pass;
2209 begin_info.framebuffer = context_vk->vk_framebuffer;
2210 begin_info.renderArea.offset.x = 0;
2211 begin_info.renderArea.offset.y = 0;
2212 begin_info.renderArea.extent.width = fb_width;
2213 begin_info.renderArea.extent.height = fb_height;
2214 begin_info.clearValueCount = 0;
2215 begin_info.pClearValues = NULL;
2216 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2218 return true;
2221 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2222 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2224 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2225 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2226 const struct wined3d_stream_state *stream;
2227 const VkDescriptorBufferInfo *buffer_info;
2228 struct wined3d_buffer_vk *buffer_vk;
2229 struct wined3d_buffer *buffer;
2230 unsigned int i, first, count;
2232 first = 0;
2233 count = 0;
2234 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2236 stream = &state->streams[i];
2238 if ((buffer = stream->buffer))
2240 buffer_vk = wined3d_buffer_vk(buffer);
2241 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2242 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2243 buffers[count] = buffer_info->buffer;
2244 offsets[count] = buffer_info->offset + stream->offset;
2245 ++count;
2246 continue;
2249 if (count)
2250 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2251 first = i + 1;
2252 count = 0;
2255 if (count)
2256 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2259 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2260 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2262 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2263 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2264 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2265 const struct wined3d_stream_output *stream;
2266 const VkDescriptorBufferInfo *buffer_info;
2267 struct wined3d_buffer_vk *buffer_vk;
2268 struct wined3d_buffer *buffer;
2269 unsigned int i, first, count;
2271 first = 0;
2272 count = 0;
2273 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2275 stream = &state->stream_output[i];
2277 if ((buffer = stream->buffer))
2279 buffer_vk = wined3d_buffer_vk(buffer);
2280 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2281 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2282 buffers[count] = buffer_info->buffer;
2283 if ((offsets[count] = stream->offset) == ~0u)
2285 FIXME("Appending to stream output buffers not implemented.\n");
2286 offsets[count] = 0;
2288 sizes[count] = buffer_info->range - offsets[count];
2289 offsets[count] += buffer_info->offset;
2290 ++count;
2291 continue;
2294 if (count)
2295 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2296 first = i + 1;
2297 count = 0;
2300 if (count)
2301 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2304 static VkResult wined3d_context_vk_create_descriptor_pool(struct wined3d_device_vk *device_vk,
2305 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2307 struct VkDescriptorPoolCreateInfo pool_desc;
2308 VkResult vr;
2310 static const VkDescriptorPoolSize pool_sizes[] =
2312 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2313 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2314 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2315 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2316 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2317 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2320 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2321 pool_desc.pNext = NULL;
2322 pool_desc.flags = 0;
2323 pool_desc.maxSets = 512;
2324 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2325 pool_desc.pPoolSizes = pool_sizes;
2327 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2328 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2330 return vr;
2333 static VkResult wined3d_context_vk_create_descriptor_set(struct wined3d_context_vk *context_vk,
2334 VkDescriptorSetLayout vk_set_layout, VkDescriptorSet *vk_descriptor_set)
2336 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2337 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2338 struct VkDescriptorSetAllocateInfo set_desc;
2339 VkResult vr;
2341 if (!context_vk->vk_descriptor_pool && (vr = wined3d_context_vk_create_descriptor_pool(device_vk,
2342 vk_info, &context_vk->vk_descriptor_pool)))
2344 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2345 return vr;
2348 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2349 set_desc.pNext = NULL;
2350 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2351 set_desc.descriptorSetCount = 1;
2352 set_desc.pSetLayouts = &vk_set_layout;
2353 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2354 return vr;
2356 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2358 wined3d_context_vk_destroy_descriptor_pool(context_vk,
2359 context_vk->vk_descriptor_pool, context_vk->current_command_buffer.id);
2360 context_vk->vk_descriptor_pool = VK_NULL_HANDLE;
2361 if ((vr = wined3d_context_vk_create_descriptor_pool(device_vk, vk_info, &context_vk->vk_descriptor_pool)))
2363 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2364 return vr;
2367 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2368 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2369 return vr;
2372 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2374 return vr;
2377 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2378 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2379 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2380 const VkBufferView *buffer_view)
2382 SIZE_T write_count = writes->count;
2383 VkWriteDescriptorSet *write;
2385 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2386 write_count + 1, sizeof(*writes->writes)))
2387 return false;
2389 write = &writes->writes[write_count];
2390 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2391 write->pNext = NULL;
2392 write->dstSet = vk_descriptor_set;
2393 write->dstBinding = binding_idx;
2394 write->dstArrayElement = 0;
2395 write->descriptorCount = 1;
2396 write->descriptorType = type;
2397 write->pImageInfo = image_info;
2398 write->pBufferInfo = buffer_info;
2399 write->pTexelBufferView = buffer_view;
2401 ++writes->count;
2403 return true;
2406 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2407 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2408 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2410 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2412 switch (type)
2414 case WINED3D_SHADER_RESOURCE_BUFFER:
2415 if (data_type == WINED3D_DATA_FLOAT)
2416 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2417 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2418 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2419 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2421 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2422 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2423 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2425 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2426 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2427 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2429 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2430 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2431 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2433 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2434 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2435 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2437 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2438 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2439 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2441 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2442 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2443 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2445 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2446 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2447 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2449 default:
2450 FIXME("Unhandled resource type %#x.\n", type);
2451 return false;
2455 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
2456 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
2458 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
2459 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2460 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2461 const struct wined3d_shader_resource_binding *binding;
2462 struct wined3d_shader_resource_bindings *bindings;
2463 struct wined3d_unordered_access_view_vk *uav_vk;
2464 struct wined3d_shader_resource_view_vk *srv_vk;
2465 struct wined3d_unordered_access_view *uav;
2466 const VkDescriptorBufferInfo *buffer_info;
2467 struct wined3d_shader_resource_view *srv;
2468 const VkDescriptorImageInfo *image_info;
2469 struct wined3d_buffer_vk *buffer_vk;
2470 VkDescriptorSetLayout vk_set_layout;
2471 VkPipelineLayout vk_pipeline_layout;
2472 struct wined3d_resource *resource;
2473 VkPipelineBindPoint vk_bind_point;
2474 VkDescriptorSet vk_descriptor_set;
2475 struct wined3d_view_vk *view_vk;
2476 struct wined3d_sampler *sampler;
2477 struct wined3d_buffer *buffer;
2478 VkBufferView *buffer_view;
2479 VkDescriptorType type;
2480 VkResult vr;
2481 size_t i;
2483 switch (pipeline)
2485 case WINED3D_PIPELINE_GRAPHICS:
2486 bindings = &context_vk->graphics.bindings;
2487 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2488 vk_set_layout = context_vk->graphics.vk_set_layout;
2489 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
2490 break;
2492 case WINED3D_PIPELINE_COMPUTE:
2493 bindings = &context_vk->compute.bindings;
2494 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2495 vk_set_layout = context_vk->compute.vk_set_layout;
2496 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
2497 break;
2499 default:
2500 ERR("Invalid pipeline %#x.\n", pipeline);
2501 return false;
2504 if ((vr = wined3d_context_vk_create_descriptor_set(context_vk, vk_set_layout, &vk_descriptor_set)))
2506 WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2507 return false;
2510 writes->count = 0;
2511 for (i = 0; i < bindings->count; ++i)
2513 binding = &bindings->bindings[i];
2515 switch (binding->shader_descriptor_type)
2517 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
2518 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx]))
2520 FIXME("NULL constant buffer views not implemented.\n");
2521 return false;
2523 buffer_vk = wined3d_buffer_vk(buffer);
2524 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2525 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2526 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
2527 return false;
2528 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2529 break;
2531 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
2532 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
2534 if (!wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
2535 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk))
2536 return false;
2537 break;
2539 resource = srv->resource;
2541 srv_vk = wined3d_shader_resource_view_vk(srv);
2542 view_vk = &srv_vk->view_vk;
2543 if (resource->type == WINED3D_RTYPE_BUFFER)
2545 image_info = NULL;
2546 buffer_view = &view_vk->u.vk_buffer_view;
2547 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
2549 else
2551 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2553 if (view_vk->u.vk_image_info.imageView)
2554 image_info = &view_vk->u.vk_image_info;
2555 else
2556 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2557 buffer_view = NULL;
2558 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2561 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2562 binding->binding_idx, type, NULL, image_info, buffer_view))
2563 return false;
2564 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
2565 break;
2567 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
2568 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2570 FIXME("NULL unordered access views not implemented.\n");
2571 return false;
2573 resource = uav->resource;
2575 uav_vk = wined3d_unordered_access_view_vk(uav);
2576 view_vk = &uav_vk->view_vk;
2577 if (resource->type == WINED3D_RTYPE_BUFFER)
2579 image_info = NULL;
2580 buffer_view = &view_vk->u.vk_buffer_view;
2581 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2583 else
2585 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2587 if (view_vk->u.vk_image_info.imageView)
2588 image_info = &view_vk->u.vk_image_info;
2589 else
2590 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2591 buffer_view = NULL;
2592 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2595 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2596 binding->binding_idx, type, NULL, image_info, buffer_view))
2597 return false;
2598 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
2599 break;
2601 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
2602 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2604 FIXME("NULL unordered access view counters not implemented.\n");
2605 return false;
2608 uav_vk = wined3d_unordered_access_view_vk(uav);
2609 if (!uav_vk->vk_counter_view || !wined3d_shader_descriptor_writes_vk_add_write(writes,
2610 vk_descriptor_set, binding->binding_idx, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
2611 NULL, NULL, &uav_vk->vk_counter_view))
2612 return false;
2613 break;
2615 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
2616 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
2617 sampler = context_vk->c.device->null_sampler;
2618 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2619 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
2620 return false;
2621 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
2622 break;
2624 default:
2625 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
2626 return false;
2630 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
2631 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
2632 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
2634 return true;
2637 static VkResult wined3d_context_vk_create_descriptor_set_layout(struct wined3d_device_vk *device_vk,
2638 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
2639 VkDescriptorSetLayout *vk_set_layout)
2641 VkDescriptorSetLayoutCreateInfo layout_desc;
2642 VkResult vr;
2644 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2645 layout_desc.pNext = NULL;
2646 layout_desc.flags = 0;
2647 layout_desc.bindingCount = key->binding_count;
2648 layout_desc.pBindings = key->bindings;
2650 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
2651 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
2653 return vr;
2656 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
2657 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
2659 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2660 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2661 struct wined3d_pipeline_layout_key_vk key;
2662 struct wined3d_pipeline_layout_vk *layout;
2663 VkPipelineLayoutCreateInfo layout_desc;
2664 struct wine_rb_entry *entry;
2665 VkResult vr;
2667 key.bindings = bindings;
2668 key.binding_count = binding_count;
2669 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
2670 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
2672 if (!(layout = heap_alloc(sizeof(*layout))))
2673 return NULL;
2675 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
2677 heap_free(layout);
2678 return NULL;
2680 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
2681 layout->key.binding_count = key.binding_count;
2683 if ((vr = wined3d_context_vk_create_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
2685 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
2686 goto fail;
2689 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
2690 layout_desc.pNext = NULL;
2691 layout_desc.flags = 0;
2692 layout_desc.setLayoutCount = 1;
2693 layout_desc.pSetLayouts = &layout->vk_set_layout;
2694 layout_desc.pushConstantRangeCount = 0;
2695 layout_desc.pPushConstantRanges = NULL;
2697 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
2698 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
2700 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
2701 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
2702 goto fail;
2705 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
2707 ERR("Failed to insert pipeline layout.\n");
2708 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
2709 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
2710 goto fail;
2713 return layout;
2715 fail:
2716 heap_free(layout->key.bindings);
2717 heap_free(layout);
2718 return NULL;
2721 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
2723 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2724 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2725 struct wined3d_graphics_pipeline_vk *pipeline_vk;
2726 struct wined3d_graphics_pipeline_key_vk *key;
2727 struct wine_rb_entry *entry;
2728 VkResult vr;
2730 key = &context_vk->graphics.pipeline_key_vk;
2731 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
2732 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
2734 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
2735 return VK_NULL_HANDLE;
2736 pipeline_vk->key = *key;
2738 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
2739 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
2741 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
2742 heap_free(pipeline_vk);
2743 return VK_NULL_HANDLE;
2746 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
2747 ERR("Failed to insert pipeline.\n");
2749 return pipeline_vk->vk_pipeline;
2752 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
2753 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
2755 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
2756 const struct wined3d_shader_resource_bindings *bindings;
2757 const struct wined3d_shader_resource_binding *binding;
2758 struct wined3d_unordered_access_view_vk *uav_vk;
2759 struct wined3d_shader_resource_view_vk *srv_vk;
2760 struct wined3d_unordered_access_view *uav;
2761 struct wined3d_shader_resource_view *srv;
2762 struct wined3d_buffer_vk *buffer_vk;
2763 struct wined3d_sampler *sampler;
2764 struct wined3d_buffer *buffer;
2765 size_t i;
2767 switch (pipeline)
2769 case WINED3D_PIPELINE_GRAPHICS:
2770 bindings = &context_vk->graphics.bindings;
2771 break;
2773 case WINED3D_PIPELINE_COMPUTE:
2774 bindings = &context_vk->compute.bindings;
2775 break;
2777 default:
2778 ERR("Invalid pipeline %#x.\n", pipeline);
2779 return;
2782 writes->count = 0;
2783 for (i = 0; i < bindings->count; ++i)
2785 binding = &bindings->bindings[i];
2787 switch (binding->shader_descriptor_type)
2789 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
2790 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx]))
2791 break;
2793 buffer_vk = wined3d_buffer_vk(buffer);
2794 wined3d_buffer_load(buffer, &context_vk->c, state);
2795 if (!buffer_vk->bo_user.valid)
2797 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
2798 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
2799 else
2800 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
2802 break;
2804 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
2805 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
2806 break;
2808 srv_vk = wined3d_shader_resource_view_vk(srv);
2809 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
2811 if (!srv_vk->view_vk.bo_user.valid)
2813 wined3d_shader_resource_view_vk_update(srv_vk, context_vk);
2814 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
2815 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
2816 else
2817 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
2819 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
2821 else
2823 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
2825 break;
2827 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
2828 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2829 break;
2831 uav_vk = wined3d_unordered_access_view_vk(uav);
2832 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
2834 if (!uav_vk->view_vk.bo_user.valid)
2836 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
2837 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
2838 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
2839 else
2840 context_invalidate_compute_state(&context_vk->c,
2841 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
2843 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
2844 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
2846 else
2848 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
2849 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
2851 break;
2853 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
2854 break;
2856 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
2857 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
2858 sampler = context_vk->c.device->null_sampler;
2859 break;
2861 default:
2862 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
2863 break;
2868 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
2869 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
2871 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2872 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2873 struct wined3d_rendertarget_view *dsv;
2874 VkSampleCountFlagBits sample_count;
2875 VkCommandBuffer vk_command_buffer;
2876 struct wined3d_buffer *buffer;
2877 unsigned int i;
2879 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
2880 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2881 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
2882 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2883 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
2884 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2885 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
2886 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
2887 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
2888 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
2889 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
2891 context_vk->sample_count = 0;
2892 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2894 struct wined3d_rendertarget_view *rtv;
2896 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
2897 continue;
2899 if (wined3d_blend_state_get_writemask(state->blend_state, i))
2901 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
2902 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
2904 else
2906 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
2909 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
2910 if (!context_vk->sample_count)
2911 context_vk->sample_count = sample_count;
2912 else if (context_vk->sample_count != sample_count)
2913 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
2916 if ((dsv = state->fb.depth_stencil))
2918 if (wined3d_state_uses_depth_buffer(state))
2919 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
2920 else
2921 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
2922 if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write)
2923 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
2925 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
2926 if (!context_vk->sample_count)
2927 context_vk->sample_count = sample_count;
2928 else if (context_vk->sample_count != sample_count)
2929 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
2932 if (!context_vk->sample_count)
2933 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
2934 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2936 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
2937 if (!context_vk->graphics.vk_pipeline_layout)
2939 ERR("No pipeline layout set.\n");
2940 return VK_NULL_HANDLE;
2942 context_vk->c.update_shader_resource_bindings = 1;
2943 context_vk->c.update_unordered_access_view_bindings = 1;
2946 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
2948 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2950 if (!(buffer = state->streams[i].buffer))
2951 continue;
2953 wined3d_buffer_load(buffer, &context_vk->c, state);
2954 if (!wined3d_buffer_vk(buffer)->bo_user.valid)
2955 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
2958 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
2960 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2962 if (!(buffer = state->stream_output[i].buffer))
2963 continue;
2965 wined3d_buffer_load(buffer, &context_vk->c, state);
2966 wined3d_buffer_invalidate_location(buffer, ~WINED3D_LOCATION_BUFFER);
2967 if (!wined3d_buffer_vk(buffer)->bo_user.valid)
2968 context_vk->update_stream_output = 1;
2970 context_vk->c.transform_feedback_active = 1;
2973 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
2975 wined3d_buffer_load(state->index_buffer, &context_vk->c, state);
2976 if (!wined3d_buffer_vk(state->index_buffer)->bo_user.valid)
2977 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
2980 if (indirect_vk)
2981 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
2983 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
2985 ERR("Failed to get command buffer.\n");
2986 return VK_NULL_HANDLE;
2989 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2990 wined3d_context_vk_end_current_render_pass(context_vk);
2991 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
2993 ERR("Failed to begin render pass.\n");
2994 return VK_NULL_HANDLE;
2997 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout)
2998 || !context_vk->graphics.vk_pipeline)
3000 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3002 ERR("Failed to get graphics pipeline.\n");
3003 return VK_NULL_HANDLE;
3006 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3007 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3010 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3011 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3013 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3015 context_vk->update_stream_output = 1;
3016 context_vk->c.transform_feedback_paused = 0;
3018 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3020 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3021 context_vk->update_stream_output = 0;
3024 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3026 struct wined3d_buffer_vk *buffer_vk = wined3d_buffer_vk(state->index_buffer);
3027 const VkDescriptorBufferInfo *buffer_info;
3028 VkIndexType idx_type;
3030 if (state->index_format == WINED3DFMT_R16_UINT)
3031 idx_type = VK_INDEX_TYPE_UINT16;
3032 else
3033 idx_type = VK_INDEX_TYPE_UINT32;
3034 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3035 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
3036 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3037 buffer_info->offset + state->index_offset, idx_type));
3040 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3041 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3042 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3043 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3044 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3045 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3046 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3047 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3048 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3049 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3050 context_vk->c.update_shader_resource_bindings = 1;
3051 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3052 context_vk->c.update_unordered_access_view_bindings = 1;
3054 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3056 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3058 ERR("Failed to update shader descriptors.\n");
3059 return VK_NULL_HANDLE;
3062 context_vk->c.update_shader_resource_bindings = 0;
3063 context_vk->c.update_unordered_access_view_bindings = 0;
3066 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3067 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3069 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3070 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3072 return vk_command_buffer;
3075 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3076 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3078 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3079 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3080 VkCommandBuffer vk_command_buffer;
3082 wined3d_context_vk_end_current_render_pass(context_vk);
3084 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3085 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3087 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3089 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3090 if (!context_vk->compute.vk_pipeline)
3092 ERR("No compute pipeline set.\n");
3093 return VK_NULL_HANDLE;
3095 context_vk->c.update_compute_shader_resource_bindings = 1;
3096 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3097 context_vk->update_compute_pipeline = 1;
3100 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3102 if (indirect_vk)
3103 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3105 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3107 ERR("Failed to get command buffer.\n");
3108 return VK_NULL_HANDLE;
3111 if (context_vk->update_compute_pipeline)
3113 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3114 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3115 context_vk->update_compute_pipeline = 0;
3118 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3119 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3120 context_vk->c.update_compute_shader_resource_bindings = 1;
3121 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3122 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3124 if (context_vk->c.update_compute_shader_resource_bindings
3125 || context_vk->c.update_compute_unordered_access_view_bindings)
3127 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3129 ERR("Failed to update shader descriptors.\n");
3130 return VK_NULL_HANDLE;
3133 context_vk->c.update_compute_shader_resource_bindings = 0;
3134 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3137 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3138 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3140 return vk_command_buffer;
3143 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3145 VkCommandPoolCreateInfo command_pool_info;
3146 const struct wined3d_vk_info *vk_info;
3147 struct wined3d_adapter_vk *adapter_vk;
3148 struct wined3d_device_vk *device_vk;
3149 VkResult vr;
3151 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3153 wined3d_context_init(&context_vk->c, swapchain);
3154 device_vk = wined3d_device_vk(swapchain->device);
3155 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3156 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3158 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3159 command_pool_info.pNext = NULL;
3160 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3161 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3162 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3163 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3165 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3166 wined3d_context_cleanup(&context_vk->c);
3167 return E_FAIL;
3169 context_vk->current_command_buffer.id = 1;
3171 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3173 list_init(&context_vk->active_queries);
3174 list_init(&context_vk->free_occlusion_query_pools);
3175 list_init(&context_vk->free_timestamp_query_pools);
3176 list_init(&context_vk->free_pipeline_statistics_query_pools);
3177 list_init(&context_vk->free_stream_output_statistics_query_pools);
3179 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3180 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3181 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3182 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3184 return WINED3D_OK;