Release 6.15.
[wine.git] / dlls / wined3d / context_vk.c
blob8df416851f2c4d59ed4072213157a461bf0fa36d
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 return;
283 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
284 chunk_vk->c.map_ptr = NULL;
287 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
288 unsigned int pool, size_t size)
290 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
291 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
292 VkMemoryAllocateInfo allocate_info;
293 VkDeviceMemory vk_memory;
294 VkResult vr;
296 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
297 allocate_info.pNext = NULL;
298 allocate_info.allocationSize = size;
299 allocate_info.memoryTypeIndex = pool;
300 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
302 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
303 return VK_NULL_HANDLE;
306 return vk_memory;
309 struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
310 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
312 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
313 struct wined3d_allocator *allocator = &device_vk->allocator;
314 struct wined3d_allocator_block *block;
316 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
318 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
319 return NULL;
322 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
324 *vk_memory = VK_NULL_HANDLE;
325 return NULL;
328 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
330 return block;
333 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
334 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
336 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
337 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
338 struct wined3d_bo_slab_vk_key key;
339 struct wined3d_bo_slab_vk *slab;
340 struct wine_rb_entry *entry;
341 size_t object_size, idx;
342 size_t alignment;
344 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
345 return false;
347 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
348 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
349 && limits->minTexelBufferOffsetAlignment > alignment)
350 alignment = limits->minTexelBufferOffsetAlignment;
351 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
352 alignment = limits->minUniformBufferOffsetAlignment;
353 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
354 alignment = limits->minStorageBufferOffsetAlignment;
356 object_size = (size + (alignment - 1)) & ~(alignment - 1);
357 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
358 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
359 key.memory_type = memory_type;
360 key.usage = usage;
361 key.size = 32 * object_size;
363 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
365 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
366 TRACE("Using existing bo slab %p.\n", slab);
368 else
370 if (!(slab = heap_alloc_zero(sizeof(*slab))))
372 ERR("Failed to allocate bo slab.\n");
373 return false;
376 slab->requested_memory_type = memory_type;
377 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
379 ERR("Failed to create slab bo.\n");
380 heap_free(slab);
381 return false;
383 slab->map = ~0u;
385 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
387 ERR("Failed to add slab to available tree.\n");
388 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
389 heap_free(slab);
390 return false;
393 TRACE("Created new bo slab %p.\n", slab);
396 idx = wined3d_bit_scan(&slab->map);
397 if (!slab->map)
399 if (slab->next)
401 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
402 slab->next = NULL;
404 else
406 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
410 *bo = slab->bo;
411 bo->memory = NULL;
412 bo->slab = slab;
413 bo->buffer_offset = idx * object_size;
414 bo->memory_offset = slab->bo.memory_offset + bo->buffer_offset;
415 bo->size = size;
416 list_init(&bo->users);
417 bo->command_buffer_id = 0;
419 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
420 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
421 wine_dbgstr_longlong(bo->buffer_offset), bo);
423 return true;
426 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
427 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
429 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
430 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
431 VkMemoryRequirements memory_requirements;
432 struct wined3d_adapter_vk *adapter_vk;
433 VkBufferCreateInfo create_info;
434 unsigned int memory_type_idx;
435 VkResult vr;
437 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
438 return TRUE;
440 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
442 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
443 create_info.pNext = NULL;
444 create_info.flags = 0;
445 create_info.size = size;
446 create_info.usage = usage;
447 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
448 create_info.queueFamilyIndexCount = 0;
449 create_info.pQueueFamilyIndices = NULL;
451 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
453 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
454 return FALSE;
457 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
459 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
460 memory_requirements.memoryTypeBits, memory_type);
461 if (memory_type_idx == ~0u)
463 ERR("Failed to find suitable memory type.\n");
464 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
465 return FALSE;
467 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
468 memory_type_idx, memory_requirements.size, &bo->vk_memory);
469 if (!bo->vk_memory)
471 ERR("Failed to allocate buffer memory.\n");
472 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
473 return FALSE;
475 bo->memory_offset = bo->memory ? bo->memory->offset : 0;
477 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
478 bo->vk_memory, bo->memory_offset))) < 0)
480 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
481 if (bo->memory)
482 wined3d_allocator_block_free(bo->memory);
483 else
484 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
485 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
486 return FALSE;
489 bo->map_ptr = NULL;
490 bo->buffer_offset = 0;
491 bo->size = size;
492 bo->usage = usage;
493 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
494 list_init(&bo->users);
495 bo->command_buffer_id = 0;
496 bo->slab = NULL;
498 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
499 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
501 return TRUE;
504 BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkImageType vk_image_type,
505 VkImageUsageFlags usage, VkFormat vk_format, unsigned int width, unsigned int height, unsigned int depth,
506 unsigned int sample_count, unsigned int mip_levels, unsigned int layer_count, unsigned int flags,
507 struct wined3d_image_vk *image)
509 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
510 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
511 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
512 VkMemoryRequirements memory_requirements;
513 VkImageCreateInfo create_info;
514 unsigned int memory_type_idx;
515 VkResult vr;
517 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
518 create_info.pNext = NULL;
519 create_info.flags = flags;
520 create_info.imageType = vk_image_type;
521 create_info.format = vk_format;
522 create_info.extent.width = width;
523 create_info.extent.height = height;
524 create_info.extent.depth = depth;
525 create_info.mipLevels = mip_levels;
526 create_info.arrayLayers = layer_count;
527 create_info.samples = sample_count;
528 create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
529 create_info.usage = usage;
530 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
531 create_info.queueFamilyIndexCount = 0;
532 create_info.pQueueFamilyIndices = NULL;
533 create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
535 image->command_buffer_id = 0;
537 vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &image->vk_image));
538 if (vr != VK_SUCCESS)
540 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr));
541 image->vk_image = VK_NULL_HANDLE;
542 return FALSE;
545 VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image,
546 &memory_requirements));
548 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
549 memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
550 if (memory_type_idx == ~0u)
552 ERR("Failed to find suitable image memory type.\n");
553 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
554 image->vk_image = VK_NULL_HANDLE;
555 return FALSE;
558 image->memory = wined3d_context_vk_allocate_memory(context_vk, memory_type_idx,
559 memory_requirements.size, &image->vk_memory);
560 if (!image->vk_memory)
562 ERR("Failed to allocate image memory.\n");
563 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
564 image->vk_image = VK_NULL_HANDLE;
565 return FALSE;
568 vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, image->vk_memory,
569 image->memory ? image->memory->offset : 0));
570 if (vr != VK_SUCCESS)
572 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
573 if (image->memory)
574 wined3d_allocator_block_free(image->memory);
575 else
576 VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
577 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
578 image->memory = NULL;
579 image->vk_memory = VK_NULL_HANDLE;
580 image->vk_image = VK_NULL_HANDLE;
581 return FALSE;
584 return TRUE;
587 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
589 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
590 struct wined3d_retired_object_vk *o;
592 if (retired->free)
594 o = retired->free;
595 retired->free = o->u.next;
596 return o;
599 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
600 retired->count + 1, sizeof(*retired->objects)))
601 return NULL;
603 return &retired->objects[retired->count++];
606 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk *context_vk,
607 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
609 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
610 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
611 struct wined3d_retired_object_vk *o;
613 if (context_vk->completed_command_buffer_id > command_buffer_id)
615 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
616 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
617 return;
620 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
622 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
623 return;
626 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
627 o->u.vk_framebuffer = vk_framebuffer;
628 o->command_buffer_id = command_buffer_id;
631 static void wined3d_context_vk_destroy_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
632 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
634 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
635 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
636 struct wined3d_retired_object_vk *o;
638 if (context_vk->completed_command_buffer_id > command_buffer_id)
640 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
641 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
642 return;
645 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
647 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
648 return;
651 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
652 o->u.vk_descriptor_pool = vk_descriptor_pool;
653 o->command_buffer_id = command_buffer_id;
656 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
657 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
659 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
660 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
661 struct wined3d_retired_object_vk *o;
663 if (context_vk->completed_command_buffer_id > command_buffer_id)
665 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
666 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
667 return;
670 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
672 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
673 return;
676 o->type = WINED3D_RETIRED_MEMORY_VK;
677 o->u.vk_memory = vk_memory;
678 o->command_buffer_id = command_buffer_id;
681 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
682 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
684 struct wined3d_retired_object_vk *o;
686 if (context_vk->completed_command_buffer_id > command_buffer_id)
688 wined3d_allocator_block_free(block);
689 TRACE("Freed block %p.\n", block);
690 return;
693 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
695 ERR("Leaking block %p.\n", block);
696 return;
699 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
700 o->u.block = block;
701 o->command_buffer_id = command_buffer_id;
704 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
705 SIZE_T idx, struct wined3d_context_vk *context_vk)
707 struct wined3d_bo_slab_vk_key key;
708 struct wine_rb_entry *entry;
710 TRACE("slab %p, idx %lu, context_vk %p.\n", slab, idx, context_vk);
712 if (!slab->map)
714 key.memory_type = slab->requested_memory_type;
715 key.usage = slab->bo.usage;
716 key.size = slab->bo.size;
718 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
720 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
721 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
723 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
725 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
728 slab->map |= 1u << idx;
731 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
732 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
734 struct wined3d_retired_object_vk *o;
736 if (context_vk->completed_command_buffer_id > command_buffer_id)
738 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
739 return;
742 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
744 ERR("Leaking slab %p, slice %#lx.\n", slab, idx);
745 return;
748 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
749 o->u.slice.slab = slab;
750 o->u.slice.idx = idx;
751 o->command_buffer_id = command_buffer_id;
754 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk *context_vk,
755 VkBuffer vk_buffer, uint64_t command_buffer_id)
757 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
758 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
759 struct wined3d_retired_object_vk *o;
761 if (context_vk->completed_command_buffer_id > command_buffer_id)
763 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
764 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
765 return;
768 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
770 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
771 return;
774 o->type = WINED3D_RETIRED_BUFFER_VK;
775 o->u.vk_buffer = vk_buffer;
776 o->command_buffer_id = command_buffer_id;
779 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk *context_vk,
780 VkImage vk_image, uint64_t command_buffer_id)
782 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
783 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
784 struct wined3d_retired_object_vk *o;
786 if (context_vk->completed_command_buffer_id > command_buffer_id)
788 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
789 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
790 return;
793 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
795 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
796 return;
799 o->type = WINED3D_RETIRED_IMAGE_VK;
800 o->u.vk_image = vk_image;
801 o->command_buffer_id = command_buffer_id;
804 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk *context_vk,
805 VkBufferView vk_view, uint64_t command_buffer_id)
807 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
808 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
809 struct wined3d_retired_object_vk *o;
811 if (context_vk->completed_command_buffer_id > command_buffer_id)
813 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
814 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
815 return;
818 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
820 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
821 return;
824 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
825 o->u.vk_buffer_view = vk_view;
826 o->command_buffer_id = command_buffer_id;
829 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk *context_vk,
830 VkImageView vk_view, uint64_t command_buffer_id)
832 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
833 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
834 struct wined3d_retired_object_vk *o;
836 if (context_vk->completed_command_buffer_id > command_buffer_id)
838 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
839 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
840 return;
843 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
845 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
846 return;
849 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
850 o->u.vk_image_view = vk_view;
851 o->command_buffer_id = command_buffer_id;
854 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
855 VkSampler vk_sampler, uint64_t command_buffer_id)
857 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
858 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
859 struct wined3d_retired_object_vk *o;
861 if (context_vk->completed_command_buffer_id > command_buffer_id)
863 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
864 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
865 return;
868 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
870 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
871 return;
874 o->type = WINED3D_RETIRED_SAMPLER_VK;
875 o->u.vk_sampler = vk_sampler;
876 o->command_buffer_id = command_buffer_id;
879 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
881 wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
882 if (image->memory)
883 wined3d_context_vk_destroy_allocator_block(context_vk, image->memory,
884 image->command_buffer_id);
885 else
886 wined3d_context_vk_destroy_vk_memory(context_vk, image->vk_memory, image->command_buffer_id);
888 image->vk_image = VK_NULL_HANDLE;
889 image->vk_memory = VK_NULL_HANDLE;
890 image->memory = NULL;
893 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
895 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
896 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
897 struct wined3d_bo_slab_vk *slab_vk;
898 size_t object_size, idx;
900 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
902 if ((slab_vk = bo->slab))
904 if (bo->map_ptr)
905 wined3d_bo_slab_vk_unmap(slab_vk, context_vk);
906 object_size = slab_vk->bo.size / 32;
907 idx = bo->buffer_offset / object_size;
908 wined3d_context_vk_destroy_bo_slab_slice(context_vk, slab_vk, idx, bo->command_buffer_id);
909 return;
912 wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
913 if (bo->memory)
915 if (bo->map_ptr)
916 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
917 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
918 return;
921 if (bo->map_ptr)
922 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
923 wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
925 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
926 context_vk->retired_bo_size += bo->size;
929 void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk *context_vk)
931 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
932 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
933 struct wined3d_command_buffer_vk *buffer;
934 SIZE_T i = 0;
936 while (i < context_vk->submitted.buffer_count)
938 buffer = &context_vk->submitted.buffers[i];
939 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
941 ++i;
942 continue;
945 TRACE("Command buffer %p with id 0x%s has finished.\n",
946 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
947 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
948 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
949 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
951 if (buffer->id > context_vk->completed_command_buffer_id)
952 context_vk->completed_command_buffer_id = buffer->id;
953 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
957 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk)
959 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
960 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
961 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
962 struct wined3d_retired_object_vk *o;
963 uint64_t command_buffer_id;
964 SIZE_T i = 0;
966 wined3d_context_vk_poll_command_buffers(context_vk);
967 command_buffer_id = context_vk->completed_command_buffer_id;
969 retired->free = NULL;
970 for (i = retired->count; i; --i)
972 o = &retired->objects[i - 1];
974 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
975 continue;
977 switch (o->type)
979 case WINED3D_RETIRED_FREE_VK:
980 /* Nothing to do. */
981 break;
983 case WINED3D_RETIRED_FRAMEBUFFER_VK:
984 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
985 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
986 break;
988 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
989 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, o->u.vk_descriptor_pool, NULL));
990 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
991 break;
993 case WINED3D_RETIRED_MEMORY_VK:
994 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
995 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
996 break;
998 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
999 TRACE("Destroying block %p.\n", o->u.block);
1000 wined3d_allocator_block_free(o->u.block);
1001 break;
1003 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
1004 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
1005 break;
1007 case WINED3D_RETIRED_BUFFER_VK:
1008 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
1009 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
1010 break;
1012 case WINED3D_RETIRED_IMAGE_VK:
1013 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
1014 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
1015 break;
1017 case WINED3D_RETIRED_BUFFER_VIEW_VK:
1018 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
1019 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
1020 break;
1022 case WINED3D_RETIRED_IMAGE_VIEW_VK:
1023 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
1024 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
1025 break;
1027 case WINED3D_RETIRED_SAMPLER_VK:
1028 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
1029 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
1030 break;
1032 default:
1033 ERR("Unhandled object type %#x.\n", o->type);
1034 break;
1037 if (i == retired->count)
1039 --retired->count;
1040 continue;
1043 o->type = WINED3D_RETIRED_FREE_VK;
1044 o->u.next = retired->free;
1045 retired->free = o;
1049 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
1051 struct wined3d_context_vk *context_vk = ctx;
1052 struct wined3d_bo_slab_vk *slab, *next;
1054 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
1055 while (slab)
1057 next = slab->next;
1058 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
1059 heap_free(slab);
1060 slab = next;
1064 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
1066 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
1067 struct wined3d_graphics_pipeline_vk, entry);
1068 struct wined3d_context_vk *context_vk = ctx;
1069 const struct wined3d_vk_info *vk_info;
1070 struct wined3d_device_vk *device_vk;
1072 vk_info = context_vk->vk_info;
1073 device_vk = wined3d_device_vk(context_vk->c.device);
1075 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
1076 heap_free(pipeline_vk);
1079 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
1081 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
1082 struct wined3d_pipeline_layout_vk, entry);
1083 struct wined3d_context_vk *context_vk = ctx;
1084 const struct wined3d_vk_info *vk_info;
1085 struct wined3d_device_vk *device_vk;
1087 vk_info = context_vk->vk_info;
1088 device_vk = wined3d_device_vk(context_vk->c.device);
1090 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
1091 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
1092 heap_free(layout->key.bindings);
1093 heap_free(layout);
1096 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
1097 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1099 struct wined3d_render_pass_attachment_vk *a;
1100 struct wined3d_rendertarget_view *view;
1101 unsigned int i;
1103 memset(key, 0, sizeof(*key));
1105 for (i = 0; i < rt_count; ++i)
1107 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1108 continue;
1110 a = &key->rt[i];
1111 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1112 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1113 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1114 key->rt_mask |= 1u << i;
1117 if (depth_stencil && (view = fb->depth_stencil))
1119 a = &key->ds;
1120 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1121 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1122 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1123 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1126 key->clear_flags = clear_flags;
1129 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1130 struct wined3d_context_vk *context_vk)
1132 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1133 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1135 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1138 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1139 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1141 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1142 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1143 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1144 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1145 const struct wined3d_render_pass_attachment_vk *a;
1146 VkAttachmentReference ds_attachment_reference;
1147 VkAttachmentReference *ds_reference = NULL;
1148 unsigned int attachment_count, rt_count, i;
1149 VkAttachmentDescription *attachment;
1150 VkSubpassDescription sub_pass_desc;
1151 VkRenderPassCreateInfo pass_desc;
1152 uint32_t mask;
1153 VkResult vr;
1155 rt_count = 0;
1156 attachment_count = 0;
1157 mask = key->rt_mask & wined3d_mask_from_size(WINED3D_MAX_RENDER_TARGETS);
1158 while (mask)
1160 i = wined3d_bit_scan(&mask);
1161 a = &key->rt[i];
1163 attachment = &attachments[attachment_count];
1164 attachment->flags = 0;
1165 attachment->format = a->vk_format;
1166 attachment->samples = a->vk_samples;
1167 if (key->clear_flags & WINED3DCLEAR_TARGET)
1168 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1169 else
1170 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1171 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1172 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1173 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1174 attachment->initialLayout = a->vk_layout;
1175 attachment->finalLayout = a->vk_layout;
1177 attachment_references[i].attachment = attachment_count;
1178 attachment_references[i].layout = a->vk_layout;
1180 ++attachment_count;
1181 rt_count = i + 1;
1184 mask = ~key->rt_mask & wined3d_mask_from_size(rt_count);
1185 while (mask)
1187 i = wined3d_bit_scan(&mask);
1188 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1189 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1192 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1194 a = &key->ds;
1196 attachment = &attachments[attachment_count];
1197 attachment->flags = 0;
1198 attachment->format = a->vk_format;
1199 attachment->samples = a->vk_samples;
1200 if (key->clear_flags & WINED3DCLEAR_ZBUFFER)
1201 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1202 else
1203 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1204 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1205 if (key->clear_flags & WINED3DCLEAR_STENCIL)
1206 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1207 else
1208 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1209 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1210 attachment->initialLayout = a->vk_layout;
1211 attachment->finalLayout = a->vk_layout;
1213 ds_reference = &ds_attachment_reference;
1214 ds_reference->attachment = attachment_count;
1215 ds_reference->layout = a->vk_layout;
1217 ++attachment_count;
1220 sub_pass_desc.flags = 0;
1221 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1222 sub_pass_desc.inputAttachmentCount = 0;
1223 sub_pass_desc.pInputAttachments = NULL;
1224 sub_pass_desc.colorAttachmentCount = rt_count;
1225 sub_pass_desc.pColorAttachments = attachment_references;
1226 sub_pass_desc.pResolveAttachments = NULL;
1227 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1228 sub_pass_desc.preserveAttachmentCount = 0;
1229 sub_pass_desc.pPreserveAttachments = NULL;
1231 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1232 pass_desc.pNext = NULL;
1233 pass_desc.flags = 0;
1234 pass_desc.attachmentCount = attachment_count;
1235 pass_desc.pAttachments = attachments;
1236 pass_desc.subpassCount = 1;
1237 pass_desc.pSubpasses = &sub_pass_desc;
1238 pass_desc.dependencyCount = 0;
1239 pass_desc.pDependencies = NULL;
1241 pass->key = *key;
1242 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1243 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1245 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1246 return false;
1249 return true;
1252 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1253 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1255 struct wined3d_render_pass_key_vk key;
1256 struct wined3d_render_pass_vk *pass;
1257 struct wine_rb_entry *entry;
1259 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1260 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1261 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1263 if (!(pass = heap_alloc(sizeof(*pass))))
1264 return VK_NULL_HANDLE;
1266 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1268 heap_free(pass);
1269 return VK_NULL_HANDLE;
1272 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1274 ERR("Failed to insert render pass.\n");
1275 wined3d_render_pass_vk_cleanup(pass, context_vk);
1276 heap_free(pass);
1277 return VK_NULL_HANDLE;
1280 return pass->vk_render_pass;
1283 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1285 VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1286 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1287 struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
1288 struct wined3d_query_vk *query_vk;
1290 if (context_vk->vk_render_pass)
1292 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1293 wined3d_query_vk_suspend(query_vk, context_vk);
1295 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1296 context_vk->vk_render_pass = VK_NULL_HANDLE;
1297 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1298 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1300 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1302 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1304 ERR("Failed to allocate new query.\n");
1305 break;
1310 if (context_vk->vk_framebuffer)
1312 wined3d_context_vk_destroy_vk_framebuffer(context_vk,
1313 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1314 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1317 if (vk_command_buffer)
1319 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
1320 struct wined3d_query_pool_vk, completed_entry)
1322 list_remove(&pool_vk->completed_entry);
1323 list_init(&pool_vk->completed_entry);
1324 wined3d_query_pool_vk_reset(pool_vk, context_vk, vk_command_buffer);
1329 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1331 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1332 struct wined3d_render_pass_vk, entry);
1334 wined3d_render_pass_vk_cleanup(pass, ctx);
1335 heap_free(pass);
1338 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1340 heap_free(writes->writes);
1343 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1345 struct wined3d_query_pool_vk *pool_vk, *entry;
1347 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1349 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1350 heap_free(pool_vk);
1354 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1355 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1357 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1358 struct wined3d_query_pool_vk *pool_vk, *entry;
1359 struct list *free_pools;
1360 size_t idx;
1362 switch (type)
1364 case WINED3D_QUERY_TYPE_OCCLUSION:
1365 free_pools = &context_vk->free_occlusion_query_pools;
1366 break;
1368 case WINED3D_QUERY_TYPE_TIMESTAMP:
1369 free_pools = &context_vk->free_timestamp_query_pools;
1370 break;
1372 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1373 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1374 break;
1376 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1377 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1378 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1379 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1380 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1381 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1382 break;
1384 default:
1385 FIXME("Unhandled query type %#x.\n", type);
1386 return false;
1389 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1391 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1392 goto done;
1393 list_remove(&pool_vk->entry);
1396 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1397 return false;
1398 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1400 heap_free(pool_vk);
1401 return false;
1404 if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET])
1406 VK_CALL(vkResetQueryPoolEXT(wined3d_device_vk(context_vk->c.device)->vk_device,
1407 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1409 else
1411 wined3d_context_vk_end_current_render_pass(context_vk);
1412 VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
1413 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1416 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1418 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1419 heap_free(pool_vk);
1420 return false;
1423 done:
1424 pool_idx->pool_vk = pool_vk;
1425 pool_idx->idx = idx;
1427 return true;
1430 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1432 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1433 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1434 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1436 if (buffer->vk_command_buffer)
1438 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1439 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1440 buffer->vk_command_buffer = VK_NULL_HANDLE;
1443 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1444 context_vk->completed_command_buffer_id = buffer->id;
1446 heap_free(context_vk->compute.bindings.bindings);
1447 heap_free(context_vk->graphics.bindings.bindings);
1448 if (context_vk->vk_descriptor_pool)
1449 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pool, NULL));
1450 if (context_vk->vk_framebuffer)
1451 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1452 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1453 if (context_vk->vk_so_counter_bo.vk_buffer)
1454 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1455 wined3d_context_vk_cleanup_resources(context_vk);
1456 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1457 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1458 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1459 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1460 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1461 heap_free(context_vk->pending_queries.queries);
1462 heap_free(context_vk->submitted.buffers);
1463 heap_free(context_vk->retired.objects);
1465 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1466 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1467 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1468 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1470 wined3d_context_cleanup(&context_vk->c);
1473 void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk *context_vk,
1474 struct wined3d_query_vk *query_vk)
1476 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1477 struct wined3d_pending_query_vk *p;
1478 size_t i;
1480 pending->free_idx = ~(size_t)0;
1481 for (i = pending->count; i; --i)
1483 p = &pending->queries[i - 1];
1485 if (p->query_vk)
1487 if (p->query_vk != query_vk && !wined3d_query_vk_accumulate_data(p->query_vk, context_vk, &p->pool_idx))
1488 continue;
1489 --p->query_vk->pending_count;
1492 if (i == pending->count)
1494 --pending->count;
1495 continue;
1498 p->query_vk = NULL;
1499 p->pool_idx.pool_vk = NULL;
1500 p->pool_idx.idx = pending->free_idx;
1501 pending->free_idx = i - 1;
1505 void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk *context_vk)
1507 wined3d_context_vk_remove_pending_queries(context_vk, NULL);
1510 void wined3d_context_vk_add_pending_query(struct wined3d_context_vk *context_vk, struct wined3d_query_vk *query_vk)
1512 struct wined3d_pending_queries_vk *pending = &context_vk->pending_queries;
1513 struct wined3d_pending_query_vk *p;
1515 if (pending->free_idx != ~(size_t)0)
1517 p = &pending->queries[pending->free_idx];
1518 pending->free_idx = p->pool_idx.idx;
1520 else
1522 if (!wined3d_array_reserve((void **)&pending->queries, &pending->size,
1523 pending->count + 1, sizeof(*pending->queries)))
1525 ERR("Failed to allocate entry.\n");
1526 return;
1528 p = &pending->queries[pending->count++];
1531 p->query_vk = query_vk;
1532 p->pool_idx = query_vk->pool_idx;
1533 ++query_vk->pending_count;
1536 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1538 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1539 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1540 VkCommandBufferAllocateInfo command_buffer_info;
1541 struct wined3d_command_buffer_vk *buffer;
1542 VkCommandBufferBeginInfo begin_info;
1543 struct wined3d_query_vk *query_vk;
1544 VkResult vr;
1546 TRACE("context_vk %p.\n", context_vk);
1548 buffer = &context_vk->current_command_buffer;
1549 if (buffer->vk_command_buffer)
1551 if (context_vk->retired_bo_size > WINED3D_RETIRED_BO_SIZE_THRESHOLD)
1552 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1553 else
1555 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1556 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1557 return buffer->vk_command_buffer;
1561 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1562 command_buffer_info.pNext = NULL;
1563 command_buffer_info.commandPool = context_vk->vk_command_pool;
1564 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1565 command_buffer_info.commandBufferCount = 1;
1566 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1567 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1569 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1570 return VK_NULL_HANDLE;
1573 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1574 begin_info.pNext = NULL;
1575 begin_info.flags = 0;
1576 begin_info.pInheritanceInfo = NULL;
1577 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1579 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1580 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1581 1, &buffer->vk_command_buffer));
1582 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1585 wined3d_context_vk_accumulate_pending_queries(context_vk);
1586 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1588 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1590 ERR("Failed to allocate new query.\n");
1591 break;
1594 wined3d_query_vk_resume(query_vk, context_vk);
1597 TRACE("Created new command buffer %p with id 0x%s.\n",
1598 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1600 return buffer->vk_command_buffer;
1603 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1604 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1605 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1607 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1608 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1609 struct wined3d_command_buffer_vk *buffer;
1610 struct wined3d_query_vk *query_vk;
1611 VkFenceCreateInfo fence_desc;
1612 VkSubmitInfo submit_info;
1613 VkResult vr;
1615 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1616 "signal_semaphore_count %u, signal_semaphores %p.\n",
1617 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1618 signal_semaphore_count, signal_semaphores);
1620 buffer = &context_vk->current_command_buffer;
1621 if (!buffer->vk_command_buffer)
1622 return;
1624 TRACE("Submitting command buffer %p with id 0x%s.\n",
1625 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1627 wined3d_context_vk_end_current_render_pass(context_vk);
1629 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1630 wined3d_query_vk_suspend(query_vk, context_vk);
1632 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1633 context_vk->update_compute_pipeline = 1;
1634 context_vk->update_stream_output = 1;
1635 context_vk->c.update_shader_resource_bindings = 1;
1636 context_vk->c.update_compute_shader_resource_bindings = 1;
1637 context_vk->c.update_unordered_access_view_bindings = 1;
1638 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1639 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1640 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1641 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1642 context_invalidate_state(&context_vk->c, STATE_STENCIL_REF);
1644 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1646 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1647 fence_desc.pNext = NULL;
1648 fence_desc.flags = 0;
1649 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1650 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1652 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1653 submit_info.pNext = NULL;
1654 submit_info.waitSemaphoreCount = wait_semaphore_count;
1655 submit_info.pWaitSemaphores = wait_semaphores;
1656 submit_info.pWaitDstStageMask = wait_stages;
1657 submit_info.commandBufferCount = 1;
1658 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1659 submit_info.signalSemaphoreCount = signal_semaphore_count;
1660 submit_info.pSignalSemaphores = signal_semaphores;
1662 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1663 ERR("Failed to submit command buffer %p, vr %s.\n",
1664 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1666 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1667 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1668 ERR("Failed to grow submitted command buffer array.\n");
1670 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1672 buffer->vk_command_buffer = VK_NULL_HANDLE;
1673 /* We don't expect this to ever happen, but handle it anyway. */
1674 if (!++buffer->id)
1676 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1677 context_vk->completed_command_buffer_id = 0;
1678 buffer->id = 1;
1680 context_vk->retired_bo_size = 0;
1681 wined3d_context_vk_cleanup_resources(context_vk);
1684 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1686 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1687 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1688 SIZE_T i;
1690 if (id <= context_vk->completed_command_buffer_id
1691 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1692 return;
1694 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1696 if (context_vk->submitted.buffers[i].id != id)
1697 continue;
1699 VK_CALL(vkWaitForFences(device_vk->vk_device, 1,
1700 &context_vk->submitted.buffers[i].vk_fence, VK_TRUE, UINT64_MAX));
1701 wined3d_context_vk_cleanup_resources(context_vk);
1702 return;
1705 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1708 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1709 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1710 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1711 VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range)
1713 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1714 VkImageMemoryBarrier barrier;
1716 wined3d_context_vk_end_current_render_pass(context_vk);
1718 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1719 barrier.pNext = NULL;
1720 barrier.srcAccessMask = src_access_mask;
1721 barrier.dstAccessMask = dst_access_mask;
1722 barrier.oldLayout = old_layout;
1723 barrier.newLayout = new_layout;
1724 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1725 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1726 barrier.image = image;
1727 barrier.subresourceRange = *range;
1729 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1732 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1734 const struct wined3d_render_pass_key_vk *k = key;
1735 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1736 const struct wined3d_render_pass_vk, entry);
1738 return memcmp(k, &pass->key, sizeof(*k));
1741 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1743 const struct wined3d_pipeline_layout_key_vk *a = key;
1744 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1745 const struct wined3d_pipeline_layout_vk, entry)->key;
1747 if (a->binding_count != b->binding_count)
1748 return a->binding_count - b->binding_count;
1749 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1752 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1754 const struct wined3d_graphics_pipeline_key_vk *a = key;
1755 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1756 const struct wined3d_graphics_pipeline_vk, entry)->key;
1757 unsigned int i;
1758 int ret;
1760 if (a->pipeline_desc.stageCount != b->pipeline_desc.stageCount)
1761 return a->pipeline_desc.stageCount - b->pipeline_desc.stageCount;
1762 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
1764 if (a->stages[i].module != b->stages[i].module)
1765 return a->stages[i].module - b->stages[i].module;
1768 if (a->divisor_desc.vertexBindingDivisorCount != b->divisor_desc.vertexBindingDivisorCount)
1769 return a->divisor_desc.vertexBindingDivisorCount - b->divisor_desc.vertexBindingDivisorCount;
1770 if ((ret = memcmp(a->divisors, b->divisors,
1771 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
1772 return ret;
1774 if (a->input_desc.vertexAttributeDescriptionCount != b->input_desc.vertexAttributeDescriptionCount)
1775 return a->input_desc.vertexAttributeDescriptionCount - b->input_desc.vertexAttributeDescriptionCount;
1776 if ((ret = memcmp(a->attributes, b->attributes,
1777 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
1778 return ret;
1779 if (a->input_desc.vertexBindingDescriptionCount != b->input_desc.vertexBindingDescriptionCount)
1780 return a->input_desc.vertexBindingDescriptionCount - b->input_desc.vertexBindingDescriptionCount;
1781 if ((ret = memcmp(a->bindings, b->bindings,
1782 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
1783 return ret;
1785 if (a->ia_desc.topology != b->ia_desc.topology)
1786 return a->ia_desc.topology - b->ia_desc.topology;
1787 if (a->ia_desc.primitiveRestartEnable != b->ia_desc.primitiveRestartEnable)
1788 return a->ia_desc.primitiveRestartEnable - b->ia_desc.primitiveRestartEnable;
1790 if (a->ts_desc.patchControlPoints != b->ts_desc.patchControlPoints)
1791 return a->ts_desc.patchControlPoints - b->ts_desc.patchControlPoints;
1793 if ((ret = memcmp(&a->viewport, &b->viewport, sizeof(a->viewport))))
1794 return ret;
1796 if ((ret = memcmp(&a->scissor, &b->scissor, sizeof(a->scissor))))
1797 return ret;
1799 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
1800 return ret;
1802 if (a->ms_desc.rasterizationSamples != b->ms_desc.rasterizationSamples)
1803 return a->ms_desc.rasterizationSamples - b->ms_desc.rasterizationSamples;
1804 if (a->ms_desc.alphaToCoverageEnable != b->ms_desc.alphaToCoverageEnable)
1805 return a->ms_desc.alphaToCoverageEnable - b->ms_desc.alphaToCoverageEnable;
1806 if (a->sample_mask != b->sample_mask)
1807 return a->sample_mask - b->sample_mask;
1809 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
1810 return ret;
1812 if (a->blend_desc.attachmentCount != b->blend_desc.attachmentCount)
1813 return a->blend_desc.attachmentCount - b->blend_desc.attachmentCount;
1814 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
1815 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
1816 return ret;
1818 if (a->pipeline_desc.layout != b->pipeline_desc.layout)
1819 return a->pipeline_desc.layout - b->pipeline_desc.layout;
1821 if (a->pipeline_desc.renderPass != b->pipeline_desc.renderPass)
1822 return a->pipeline_desc.renderPass - b->pipeline_desc.renderPass;
1824 return 0;
1827 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
1829 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
1830 const struct wined3d_bo_slab_vk_key *k = key;
1832 if (k->memory_type != slab->requested_memory_type)
1833 return k->memory_type - slab->requested_memory_type;
1834 if (k->usage != slab->bo.usage)
1835 return k->usage - slab->bo.usage;
1836 return k->size - slab->bo.size;
1839 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
1841 struct wined3d_graphics_pipeline_key_vk *key;
1842 VkPipelineShaderStageCreateInfo *stage;
1843 unsigned int i;
1845 static const VkDynamicState dynamic_states[] =
1847 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
1848 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
1851 key = &context_vk->graphics.pipeline_key_vk;
1852 memset(key, 0, sizeof(*key));
1854 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
1856 stage = &key->stages[i];
1857 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
1858 stage->pName = "main";
1861 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
1862 key->input_desc.pVertexBindingDescriptions = key->bindings;
1863 key->input_desc.pVertexAttributeDescriptions = key->attributes;
1865 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
1866 key->divisor_desc.pVertexBindingDivisors = key->divisors;
1868 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
1870 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
1872 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
1873 key->vp_desc.viewportCount = 1;
1874 key->vp_desc.pViewports = &key->viewport;
1875 key->vp_desc.scissorCount = 1;
1876 key->vp_desc.pScissors = &key->scissor;
1878 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
1879 key->rs_desc.lineWidth = 1.0f;
1881 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
1882 key->ms_desc.pSampleMask = &key->sample_mask;
1884 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
1885 key->ds_desc.maxDepthBounds = 1.0f;
1887 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
1888 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
1889 key->blend_desc.pAttachments = key->blend_attachments;
1890 key->blend_desc.blendConstants[0] = 1.0f;
1891 key->blend_desc.blendConstants[1] = 1.0f;
1892 key->blend_desc.blendConstants[2] = 1.0f;
1893 key->blend_desc.blendConstants[3] = 1.0f;
1895 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
1896 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
1897 key->dynamic_desc.pDynamicStates = dynamic_states;
1899 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
1900 key->pipeline_desc.pStages = key->stages;
1901 key->pipeline_desc.pVertexInputState = &key->input_desc;
1902 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
1903 key->pipeline_desc.pTessellationState = &key->ts_desc;
1904 key->pipeline_desc.pViewportState = &key->vp_desc;
1905 key->pipeline_desc.pRasterizationState = &key->rs_desc;
1906 key->pipeline_desc.pMultisampleState = &key->ms_desc;
1907 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
1908 key->pipeline_desc.pColorBlendState = &key->blend_desc;
1909 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
1910 key->pipeline_desc.basePipelineIndex = -1;
1913 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
1914 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1916 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
1917 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
1918 const struct wined3d_rasterizer_state_desc *r;
1919 float scale_bias;
1920 union
1922 uint32_t u32;
1923 float f32;
1924 } const_bias;
1926 if (!state->rasterizer_state)
1928 desc->depthClampEnable = VK_FALSE;
1929 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1930 desc->cullMode = VK_CULL_MODE_BACK_BIT;
1931 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
1932 desc->depthBiasEnable = VK_FALSE;
1933 desc->depthBiasConstantFactor = 0.0f;
1934 desc->depthBiasClamp = 0.0f;
1935 desc->depthBiasSlopeFactor = 0.0f;
1937 return;
1940 r = &state->rasterizer_state->desc;
1941 desc->depthClampEnable = !r->depth_clip;
1942 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
1943 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
1944 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
1946 scale_bias = r->scale_bias;
1947 const_bias.f32 = r->depth_bias;
1948 if (!scale_bias && !const_bias.f32)
1950 desc->depthBiasEnable = VK_FALSE;
1951 desc->depthBiasConstantFactor = 0.0f;
1952 desc->depthBiasClamp = 0.0f;
1953 desc->depthBiasSlopeFactor = 0.0f;
1955 return;
1958 desc->depthBiasEnable = VK_TRUE;
1959 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
1961 const struct wined3d_rendertarget_view *dsv;
1963 if ((dsv = state->fb.depth_stencil))
1965 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
1966 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
1968 else
1970 desc->depthBiasConstantFactor = 0.0f;
1971 desc->depthBiasSlopeFactor = 0.0f;
1974 else
1976 desc->depthBiasConstantFactor = const_bias.f32;
1977 desc->depthBiasSlopeFactor = scale_bias;
1979 desc->depthBiasClamp = r->depth_bias_clamp;
1982 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
1983 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
1985 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
1986 const struct wined3d_blend_state_desc *b;
1987 unsigned int i;
1989 desc->attachmentCount = context_vk->rt_count;
1991 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
1992 if (!state->blend_state)
1994 for (i = 0; i < context_vk->rt_count; ++i)
1996 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
1997 | VK_COLOR_COMPONENT_G_BIT
1998 | VK_COLOR_COMPONENT_B_BIT
1999 | VK_COLOR_COMPONENT_A_BIT;
2002 return;
2005 b = &state->blend_state->desc;
2006 for (i = 0; i < context_vk->rt_count; ++i)
2008 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2009 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2010 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2011 enum wined3d_blend src_blend, dst_blend;
2012 const struct wined3d_format *rt_format;
2014 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2015 if (!rt->enable)
2016 continue;
2018 if (rtv)
2019 rt_format = rtv->format;
2020 else
2021 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2022 a->blendEnable = VK_TRUE;
2024 src_blend = rt->src;
2025 dst_blend = rt->dst;
2026 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2028 src_blend = WINED3D_BLEND_SRCALPHA;
2029 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2031 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2033 src_blend = WINED3D_BLEND_INVSRCALPHA;
2034 dst_blend = WINED3D_BLEND_SRCALPHA;
2036 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2037 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2038 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2040 src_blend = rt->src_alpha;
2041 dst_blend = rt->dst_alpha;
2042 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2043 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2044 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2048 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2050 switch (component_type)
2052 case WINED3D_TYPE_UINT:
2053 return VK_FORMAT_R32G32B32A32_UINT;
2054 case WINED3D_TYPE_INT:
2055 return VK_FORMAT_R32G32B32A32_SINT;
2056 case WINED3D_TYPE_UNKNOWN:
2057 case WINED3D_TYPE_FLOAT:
2058 return VK_FORMAT_R32G32B32A32_SFLOAT;
2060 return VK_FORMAT_UNDEFINED;
2063 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2064 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2066 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2067 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2068 struct wined3d_graphics_pipeline_key_vk *key;
2069 VkPipelineShaderStageCreateInfo *stage;
2070 struct wined3d_stream_info stream_info;
2071 struct wined3d_shader *vertex_shader;
2072 VkPrimitiveTopology vk_topology;
2073 VkShaderModule module;
2074 bool update = false;
2075 uint32_t mask;
2077 *null_buffer_binding = ~0u;
2078 key = &context_vk->graphics.pipeline_key_vk;
2080 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2082 stage_count = 0;
2083 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2085 if (!(module = context_vk->graphics.vk_modules[i]))
2086 continue;
2088 stage = &key->stages[stage_count++];
2089 stage->stage = vk_shader_stage_from_wined3d(i);
2090 stage->module = module;
2093 key->pipeline_desc.stageCount = stage_count;
2095 update = true;
2098 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2099 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2100 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2102 VkVertexInputAttributeDescription *a;
2103 VkVertexInputBindingDescription *b;
2105 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2106 divisor_count = 0;
2107 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2109 VkVertexInputBindingDivisorDescriptionEXT *d;
2110 struct wined3d_stream_info_element *e;
2111 uint32_t binding;
2113 if (!(stream_info.use_map & (1u << i)))
2114 continue;
2116 a = &key->attributes[attribute_count++];
2117 e = &stream_info.elements[i];
2118 binding = e->stream_idx;
2120 a->location = i;
2121 a->binding = binding;
2122 a->format = wined3d_format_vk(e->format)->vk_format;
2123 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2125 if (mask & (1u << binding))
2126 continue;
2127 mask |= 1u << binding;
2129 b = &key->bindings[binding_count++];
2130 b->binding = binding;
2131 b->stride = e->stride;
2132 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2134 if (e->instanced)
2136 d = &key->divisors[divisor_count++];
2137 d->binding = binding;
2138 d->divisor = e->divisor;
2142 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2143 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2145 struct wined3d_shader_signature_element *element;
2146 struct wined3d_shader_signature *signature;
2147 uint32_t null_binding, location;
2149 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2151 if (!state->streams[i].buffer)
2153 null_binding = i;
2154 break;
2158 if (i == ARRAY_SIZE(state->streams))
2160 ERR("No streams left for a null buffer binding.\n");
2162 else
2164 signature = &vertex_shader->input_signature;
2165 for (i = 0; i < signature->element_count; ++i)
2167 element = &signature->elements[i];
2168 location = element->register_idx;
2170 if (!(mask & (1u << location)) || element->sysval_semantic)
2171 continue;
2172 mask &= ~(1u << location);
2174 a = &key->attributes[attribute_count++];
2175 a->location = location;
2176 a->binding = null_binding;
2177 a->format = vk_format_from_component_type(element->component_type);
2178 a->offset = 0;
2181 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2183 b = &key->bindings[binding_count++];
2184 *null_buffer_binding = b->binding = null_binding;
2185 b->stride = 0;
2186 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2191 key->input_desc.pNext = NULL;
2192 key->input_desc.vertexBindingDescriptionCount = binding_count;
2193 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2195 if (divisor_count)
2197 key->input_desc.pNext = &key->divisor_desc;
2198 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2201 update = true;
2204 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2205 if (key->ia_desc.topology != vk_topology)
2207 key->ia_desc.topology = vk_topology;
2208 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2209 && !wined3d_primitive_type_is_list(state->primitive_type);
2211 update = true;
2214 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2216 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2218 update = true;
2221 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2222 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2223 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2225 key->viewport.x = state->viewports[0].x;
2226 key->viewport.y = state->viewports[0].y;
2227 key->viewport.width = state->viewports[0].width;
2228 key->viewport.height = state->viewports[0].height;
2229 key->viewport.minDepth = state->viewports[0].min_z;
2230 key->viewport.maxDepth = state->viewports[0].max_z;
2232 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2234 const RECT *r = &state->scissor_rects[0];
2236 key->scissor.offset.x = r->left;
2237 key->scissor.offset.y = r->top;
2238 key->scissor.extent.width = r->right - r->left;
2239 key->scissor.extent.height = r->bottom - r->top;
2241 else
2243 key->scissor.offset.x = key->viewport.x;
2244 key->scissor.offset.y = key->viewport.y;
2245 key->scissor.extent.width = key->viewport.width;
2246 key->scissor.extent.height = key->viewport.height;
2248 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2249 if (key->scissor.offset.x < 0)
2250 key->scissor.offset.x = 0;
2251 if (key->scissor.offset.y < 0)
2252 key->scissor.offset.y = 0;
2253 key->viewport.y += key->viewport.height;
2254 key->viewport.height = -key->viewport.height;
2256 update = true;
2259 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2260 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2262 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2264 update = true;
2267 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2268 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2270 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2271 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2272 key->sample_mask = state->sample_mask;
2274 update = true;
2277 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2278 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2280 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2282 if (d)
2284 key->ds_desc.depthTestEnable = d->desc.depth;
2285 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2286 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2287 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2288 if (key->ds_desc.stencilTestEnable)
2290 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2291 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2292 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2293 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2294 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2295 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2297 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2298 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2299 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2300 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2301 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2302 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2304 else
2306 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2307 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2310 else
2312 key->ds_desc.depthTestEnable = VK_TRUE;
2313 key->ds_desc.depthWriteEnable = VK_TRUE;
2314 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2315 key->ds_desc.stencilTestEnable = VK_FALSE;
2318 update = true;
2321 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2322 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2324 wined3d_context_vk_update_blend_state(context_vk, state, key);
2326 update = true;
2329 if (key->pipeline_desc.layout != vk_pipeline_layout)
2331 key->pipeline_desc.layout = vk_pipeline_layout;
2333 update = true;
2336 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2338 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2340 update = true;
2343 return update;
2346 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2347 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2349 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2350 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2351 unsigned int fb_width, fb_height, fb_layer_count;
2352 struct wined3d_rendertarget_view_vk *rtv_vk;
2353 struct wined3d_rendertarget_view *view;
2354 const VkPhysicalDeviceLimits *limits;
2355 struct wined3d_query_vk *query_vk;
2356 VkRenderPassBeginInfo begin_info;
2357 unsigned int attachment_count, i;
2358 VkFramebufferCreateInfo fb_desc;
2359 VkResult vr;
2361 if (context_vk->vk_render_pass)
2362 return true;
2364 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2365 fb_width = limits->maxFramebufferWidth;
2366 fb_height = limits->maxFramebufferHeight;
2367 fb_layer_count = limits->maxFramebufferLayers;
2368 attachment_count = 0;
2370 context_vk->rt_count = 0;
2371 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2373 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2374 continue;
2376 rtv_vk = wined3d_rendertarget_view_vk(view);
2377 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2378 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2379 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2381 if (view->width < fb_width)
2382 fb_width = view->width;
2383 if (view->height < fb_height)
2384 fb_height = view->height;
2385 if (view->layer_count < fb_layer_count)
2386 fb_layer_count = view->layer_count;
2387 context_vk->rt_count = i + 1;
2388 ++attachment_count;
2391 if ((view = state->fb.depth_stencil))
2393 rtv_vk = wined3d_rendertarget_view_vk(view);
2394 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2395 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2396 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2398 if (view->width < fb_width)
2399 fb_width = view->width;
2400 if (view->height < fb_height)
2401 fb_height = view->height;
2402 if (view->layer_count < fb_layer_count)
2403 fb_layer_count = view->layer_count;
2404 ++attachment_count;
2407 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2408 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2410 ERR("Failed to get render pass.\n");
2411 return false;
2414 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2415 fb_desc.pNext = NULL;
2416 fb_desc.flags = 0;
2417 fb_desc.renderPass = context_vk->vk_render_pass;
2418 fb_desc.attachmentCount = attachment_count;
2419 fb_desc.pAttachments = vk_views;
2420 fb_desc.width = fb_width;
2421 fb_desc.height = fb_height;
2422 fb_desc.layers = fb_layer_count;
2424 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2426 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2427 return false;
2430 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2431 begin_info.pNext = NULL;
2432 begin_info.renderPass = context_vk->vk_render_pass;
2433 begin_info.framebuffer = context_vk->vk_framebuffer;
2434 begin_info.renderArea.offset.x = 0;
2435 begin_info.renderArea.offset.y = 0;
2436 begin_info.renderArea.extent.width = fb_width;
2437 begin_info.renderArea.extent.height = fb_height;
2438 begin_info.clearValueCount = 0;
2439 begin_info.pClearValues = NULL;
2440 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2442 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2443 wined3d_query_vk_resume(query_vk, context_vk);
2444 return true;
2447 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2448 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2450 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2451 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2452 const struct wined3d_stream_state *stream;
2453 const VkDescriptorBufferInfo *buffer_info;
2454 struct wined3d_buffer_vk *buffer_vk;
2455 struct wined3d_buffer *buffer;
2456 unsigned int i, first, count;
2458 first = 0;
2459 count = 0;
2460 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2462 stream = &state->streams[i];
2464 if ((buffer = stream->buffer))
2466 buffer_vk = wined3d_buffer_vk(buffer);
2467 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2468 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2469 buffers[count] = buffer_info->buffer;
2470 offsets[count] = buffer_info->offset + stream->offset;
2471 ++count;
2472 continue;
2475 if (count)
2476 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2477 first = i + 1;
2478 count = 0;
2481 if (count)
2482 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2485 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2486 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2488 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2489 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2490 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2491 const struct wined3d_stream_output *stream;
2492 const VkDescriptorBufferInfo *buffer_info;
2493 struct wined3d_buffer_vk *buffer_vk;
2494 struct wined3d_buffer *buffer;
2495 unsigned int i, first, count;
2497 first = 0;
2498 count = 0;
2499 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2501 stream = &state->stream_output[i];
2503 if ((buffer = stream->buffer))
2505 buffer_vk = wined3d_buffer_vk(buffer);
2506 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2507 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2508 buffers[count] = buffer_info->buffer;
2509 if ((offsets[count] = stream->offset) == ~0u)
2511 FIXME("Appending to stream output buffers not implemented.\n");
2512 offsets[count] = 0;
2514 sizes[count] = buffer_info->range - offsets[count];
2515 offsets[count] += buffer_info->offset;
2516 ++count;
2517 continue;
2520 if (count)
2521 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2522 first = i + 1;
2523 count = 0;
2526 if (count)
2527 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2530 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2531 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2533 struct VkDescriptorPoolCreateInfo pool_desc;
2534 VkResult vr;
2536 static const VkDescriptorPoolSize pool_sizes[] =
2538 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2539 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2540 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2541 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2542 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2543 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2546 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2547 pool_desc.pNext = NULL;
2548 pool_desc.flags = 0;
2549 pool_desc.maxSets = 512;
2550 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2551 pool_desc.pPoolSizes = pool_sizes;
2553 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2554 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2556 return vr;
2559 static VkResult wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2560 VkDescriptorSetLayout vk_set_layout, VkDescriptorSet *vk_descriptor_set)
2562 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2563 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2564 struct VkDescriptorSetAllocateInfo set_desc;
2565 VkResult vr;
2567 if (!context_vk->vk_descriptor_pool && (vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk,
2568 vk_info, &context_vk->vk_descriptor_pool)))
2570 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2571 return vr;
2574 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2575 set_desc.pNext = NULL;
2576 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2577 set_desc.descriptorSetCount = 1;
2578 set_desc.pSetLayouts = &vk_set_layout;
2579 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2580 return vr;
2582 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2584 wined3d_context_vk_destroy_vk_descriptor_pool(context_vk,
2585 context_vk->vk_descriptor_pool, context_vk->current_command_buffer.id);
2586 context_vk->vk_descriptor_pool = VK_NULL_HANDLE;
2587 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(device_vk, vk_info, &context_vk->vk_descriptor_pool)))
2589 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2590 return vr;
2593 set_desc.descriptorPool = context_vk->vk_descriptor_pool;
2594 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, vk_descriptor_set))) >= 0)
2595 return vr;
2598 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2600 return vr;
2603 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2604 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2605 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2606 const VkBufferView *buffer_view)
2608 SIZE_T write_count = writes->count;
2609 VkWriteDescriptorSet *write;
2611 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2612 write_count + 1, sizeof(*writes->writes)))
2613 return false;
2615 write = &writes->writes[write_count];
2616 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2617 write->pNext = NULL;
2618 write->dstSet = vk_descriptor_set;
2619 write->dstBinding = binding_idx;
2620 write->dstArrayElement = 0;
2621 write->descriptorCount = 1;
2622 write->descriptorType = type;
2623 write->pImageInfo = image_info;
2624 write->pBufferInfo = buffer_info;
2625 write->pTexelBufferView = buffer_view;
2627 ++writes->count;
2629 return true;
2632 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2633 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2634 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2636 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2638 switch (type)
2640 case WINED3D_SHADER_RESOURCE_BUFFER:
2641 if (data_type == WINED3D_DATA_FLOAT)
2642 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2643 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
2644 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
2645 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
2647 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
2648 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2649 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
2651 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
2652 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2653 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
2655 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
2656 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2657 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
2659 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
2660 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2661 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
2663 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
2664 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2665 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
2667 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
2668 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2669 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
2671 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
2672 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2673 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
2675 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
2676 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2677 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
2679 default:
2680 FIXME("Unhandled resource type %#x.\n", type);
2681 return false;
2685 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2686 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2687 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
2689 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
2690 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2691 struct wined3d_buffer_vk *buffer_vk;
2692 struct wined3d_buffer *buffer;
2694 if (!(buffer = cb_state->buffer))
2695 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2696 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
2698 buffer_vk = wined3d_buffer_vk(buffer);
2699 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
2700 buffer_info->offset += cb_state->offset;
2701 buffer_info->range = min(cb_state->size, buffer_info->range);
2702 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2703 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
2704 return false;
2705 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
2706 return true;
2709 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
2710 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2711 const struct wined3d_shader_resource_binding *binding)
2713 struct wined3d_shader_resource_view_vk *srv_vk;
2714 struct wined3d_shader_resource_view *srv;
2715 const VkDescriptorImageInfo *image_info;
2716 struct wined3d_resource *resource;
2717 struct wined3d_view_vk *view_vk;
2718 VkBufferView *buffer_view;
2719 VkDescriptorType type;
2721 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
2722 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
2723 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
2725 resource = srv->resource;
2726 srv_vk = wined3d_shader_resource_view_vk(srv);
2727 view_vk = &srv_vk->view_vk;
2728 if (resource->type == WINED3D_RTYPE_BUFFER)
2730 image_info = NULL;
2731 buffer_view = &view_vk->u.vk_buffer_view;
2732 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
2734 else
2736 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2738 if (view_vk->u.vk_image_info.imageView)
2739 image_info = &view_vk->u.vk_image_info;
2740 else
2741 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2742 buffer_view = NULL;
2743 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
2746 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2747 binding->binding_idx, type, NULL, image_info, buffer_view))
2748 return false;
2749 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
2750 return true;
2753 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
2754 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2755 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2757 struct wined3d_unordered_access_view_vk *uav_vk;
2758 struct wined3d_unordered_access_view *uav;
2759 const VkDescriptorImageInfo *image_info;
2760 struct wined3d_resource *resource;
2761 struct wined3d_view_vk *view_vk;
2762 VkBufferView *buffer_view;
2763 VkDescriptorType type;
2765 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2767 FIXME("NULL unordered access views not implemented.\n");
2768 return false;
2770 resource = uav->resource;
2772 uav_vk = wined3d_unordered_access_view_vk(uav);
2773 view_vk = &uav_vk->view_vk;
2774 if (resource->type == WINED3D_RTYPE_BUFFER)
2776 image_info = NULL;
2777 buffer_view = &view_vk->u.vk_buffer_view;
2778 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
2780 else
2782 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
2784 if (view_vk->u.vk_image_info.imageView)
2785 image_info = &view_vk->u.vk_image_info;
2786 else
2787 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
2788 buffer_view = NULL;
2789 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
2792 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
2793 binding->binding_idx, type, NULL, image_info, buffer_view))
2794 return false;
2795 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
2796 return true;
2799 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
2800 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
2801 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
2802 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
2804 struct wined3d_unordered_access_view_vk *uav_vk;
2805 struct wined3d_unordered_access_view *uav;
2807 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
2809 FIXME("NULL unordered access view counters not implemented.\n");
2810 return false;
2813 uav_vk = wined3d_unordered_access_view_vk(uav);
2814 if (!uav_vk->vk_counter_view)
2815 return false;
2817 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2818 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
2821 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
2822 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
2823 const struct wined3d_shader_resource_binding *binding)
2825 struct wined3d_sampler *sampler;
2827 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
2828 sampler = context_vk->c.device->null_sampler;
2829 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
2830 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
2831 return false;
2832 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
2833 return true;
2836 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
2837 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
2839 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
2840 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
2841 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2842 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2843 const struct wined3d_shader_resource_binding *binding;
2844 struct wined3d_shader_resource_bindings *bindings;
2845 VkDescriptorSetLayout vk_set_layout;
2846 VkPipelineLayout vk_pipeline_layout;
2847 VkPipelineBindPoint vk_bind_point;
2848 VkDescriptorSet vk_descriptor_set;
2849 VkResult vr;
2850 size_t i;
2852 switch (pipeline)
2854 case WINED3D_PIPELINE_GRAPHICS:
2855 bindings = &context_vk->graphics.bindings;
2856 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
2857 vk_set_layout = context_vk->graphics.vk_set_layout;
2858 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
2859 break;
2861 case WINED3D_PIPELINE_COMPUTE:
2862 bindings = &context_vk->compute.bindings;
2863 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
2864 vk_set_layout = context_vk->compute.vk_set_layout;
2865 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
2866 break;
2868 default:
2869 ERR("Invalid pipeline %#x.\n", pipeline);
2870 return false;
2873 if ((vr = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout, &vk_descriptor_set)))
2875 WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2876 return false;
2879 writes->count = 0;
2880 for (i = 0; i < bindings->count; ++i)
2882 binding = &bindings->bindings[i];
2884 switch (binding->shader_descriptor_type)
2886 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
2887 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
2888 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
2889 return false;
2890 break;
2892 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
2893 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
2894 context_vk, vk_descriptor_set, state, binding))
2895 return false;
2896 break;
2898 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
2899 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
2900 context_vk, pipeline, vk_descriptor_set, state, binding))
2901 return false;
2902 break;
2904 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
2905 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
2906 context_vk, pipeline, vk_descriptor_set, state, binding))
2907 return false;
2908 break;
2910 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
2911 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
2912 context_vk, vk_descriptor_set, state, binding))
2913 return false;
2914 break;
2916 default:
2917 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
2918 return false;
2922 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
2923 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
2924 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
2926 return true;
2929 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
2930 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
2931 VkDescriptorSetLayout *vk_set_layout)
2933 VkDescriptorSetLayoutCreateInfo layout_desc;
2934 VkResult vr;
2936 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
2937 layout_desc.pNext = NULL;
2938 layout_desc.flags = 0;
2939 layout_desc.bindingCount = key->binding_count;
2940 layout_desc.pBindings = key->bindings;
2942 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
2943 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
2945 return vr;
2948 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
2949 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
2951 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2952 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2953 struct wined3d_pipeline_layout_key_vk key;
2954 struct wined3d_pipeline_layout_vk *layout;
2955 VkPipelineLayoutCreateInfo layout_desc;
2956 struct wine_rb_entry *entry;
2957 VkResult vr;
2959 key.bindings = bindings;
2960 key.binding_count = binding_count;
2961 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
2962 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
2964 if (!(layout = heap_alloc(sizeof(*layout))))
2965 return NULL;
2967 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
2969 heap_free(layout);
2970 return NULL;
2972 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
2973 layout->key.binding_count = key.binding_count;
2975 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
2977 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
2978 goto fail;
2981 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
2982 layout_desc.pNext = NULL;
2983 layout_desc.flags = 0;
2984 layout_desc.setLayoutCount = 1;
2985 layout_desc.pSetLayouts = &layout->vk_set_layout;
2986 layout_desc.pushConstantRangeCount = 0;
2987 layout_desc.pPushConstantRanges = NULL;
2989 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
2990 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
2992 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
2993 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
2994 goto fail;
2997 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
2999 ERR("Failed to insert pipeline layout.\n");
3000 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3001 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3002 goto fail;
3005 return layout;
3007 fail:
3008 heap_free(layout->key.bindings);
3009 heap_free(layout);
3010 return NULL;
3013 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3015 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3016 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3017 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3018 struct wined3d_graphics_pipeline_key_vk *key;
3019 struct wine_rb_entry *entry;
3020 VkResult vr;
3022 key = &context_vk->graphics.pipeline_key_vk;
3023 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3024 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3026 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3027 return VK_NULL_HANDLE;
3028 pipeline_vk->key = *key;
3030 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3031 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3033 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3034 heap_free(pipeline_vk);
3035 return VK_NULL_HANDLE;
3038 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3039 ERR("Failed to insert pipeline.\n");
3041 return pipeline_vk->vk_pipeline;
3044 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3045 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3047 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3048 const struct wined3d_shader_resource_bindings *bindings;
3049 const struct wined3d_shader_resource_binding *binding;
3050 struct wined3d_unordered_access_view_vk *uav_vk;
3051 struct wined3d_shader_resource_view_vk *srv_vk;
3052 struct wined3d_unordered_access_view *uav;
3053 struct wined3d_shader_resource_view *srv;
3054 struct wined3d_buffer_vk *buffer_vk;
3055 struct wined3d_sampler *sampler;
3056 struct wined3d_buffer *buffer;
3057 size_t i;
3059 switch (pipeline)
3061 case WINED3D_PIPELINE_GRAPHICS:
3062 bindings = &context_vk->graphics.bindings;
3063 break;
3065 case WINED3D_PIPELINE_COMPUTE:
3066 bindings = &context_vk->compute.bindings;
3067 break;
3069 default:
3070 ERR("Invalid pipeline %#x.\n", pipeline);
3071 return;
3074 writes->count = 0;
3075 for (i = 0; i < bindings->count; ++i)
3077 binding = &bindings->bindings[i];
3079 switch (binding->shader_descriptor_type)
3081 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3082 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3083 break;
3085 buffer_vk = wined3d_buffer_vk(buffer);
3086 wined3d_buffer_load(buffer, &context_vk->c, state);
3087 if (!buffer_vk->bo_user.valid)
3089 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3090 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3091 else
3092 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3094 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3095 break;
3097 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3098 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3099 break;
3101 srv_vk = wined3d_shader_resource_view_vk(srv);
3102 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3104 if (!srv_vk->view_vk.bo_user.valid)
3106 wined3d_shader_resource_view_vk_update(srv_vk, context_vk);
3107 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3108 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3109 else
3110 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3112 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3114 else
3116 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3118 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3119 break;
3121 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3122 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3123 break;
3125 uav_vk = wined3d_unordered_access_view_vk(uav);
3126 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3128 if (!uav_vk->view_vk.bo_user.valid)
3130 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3131 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3132 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3133 else
3134 context_invalidate_compute_state(&context_vk->c,
3135 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3137 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3138 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3140 else
3142 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3143 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3145 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3146 break;
3148 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3149 break;
3151 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3152 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3153 sampler = context_vk->c.device->null_sampler;
3154 break;
3156 default:
3157 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3158 break;
3163 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3164 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3166 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3167 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3168 struct wined3d_rendertarget_view *dsv;
3169 struct wined3d_buffer_vk *buffer_vk;
3170 VkSampleCountFlagBits sample_count;
3171 VkCommandBuffer vk_command_buffer;
3172 struct wined3d_buffer *buffer;
3173 uint32_t null_buffer_binding;
3174 unsigned int i;
3176 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3177 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3178 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3179 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3180 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3181 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3182 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3183 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3184 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3185 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3186 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3188 context_vk->sample_count = 0;
3189 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3191 struct wined3d_rendertarget_view *rtv;
3193 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3194 continue;
3196 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3198 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3199 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3201 else
3203 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3206 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3207 if (!context_vk->sample_count)
3208 context_vk->sample_count = sample_count;
3209 else if (context_vk->sample_count != sample_count)
3210 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3213 if ((dsv = state->fb.depth_stencil))
3215 if (wined3d_state_uses_depth_buffer(state))
3216 wined3d_rendertarget_view_load_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3217 else
3218 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3219 if (!state->depth_stencil_state || state->depth_stencil_state->desc.depth_write)
3220 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3222 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3223 if (!context_vk->sample_count)
3224 context_vk->sample_count = sample_count;
3225 else if (context_vk->sample_count != sample_count)
3226 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3229 if (!context_vk->sample_count)
3230 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3231 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3233 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3234 if (!context_vk->graphics.vk_pipeline_layout)
3236 ERR("No pipeline layout set.\n");
3237 return VK_NULL_HANDLE;
3239 context_vk->c.update_shader_resource_bindings = 1;
3240 context_vk->c.update_unordered_access_view_bindings = 1;
3243 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3245 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3247 if (!(buffer = state->streams[i].buffer))
3248 continue;
3250 buffer_vk = wined3d_buffer_vk(buffer);
3251 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3252 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3253 if (!buffer_vk->bo_user.valid)
3254 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3257 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3259 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3261 if (!(buffer = state->stream_output[i].buffer))
3262 continue;
3264 buffer_vk = wined3d_buffer_vk(buffer);
3265 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3266 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3267 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3268 if (!buffer_vk->bo_user.valid)
3269 context_vk->update_stream_output = 1;
3271 context_vk->c.transform_feedback_active = 1;
3274 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3276 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3277 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3278 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3279 if (!buffer_vk->bo_user.valid)
3280 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3283 if (indirect_vk)
3285 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3286 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3289 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3291 ERR("Failed to get command buffer.\n");
3292 return VK_NULL_HANDLE;
3295 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3296 wined3d_context_vk_end_current_render_pass(context_vk);
3297 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3299 ERR("Failed to begin render pass.\n");
3300 return VK_NULL_HANDLE;
3303 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3304 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3306 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3308 ERR("Failed to get graphics pipeline.\n");
3309 return VK_NULL_HANDLE;
3312 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3313 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3314 if (null_buffer_binding != ~0u)
3316 VkDeviceSize offset = 0;
3317 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3318 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3322 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3324 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3325 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3328 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3329 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3331 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3333 context_vk->update_stream_output = 1;
3334 context_vk->c.transform_feedback_paused = 0;
3336 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3338 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3339 context_vk->update_stream_output = 0;
3342 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3344 const VkDescriptorBufferInfo *buffer_info;
3345 VkIndexType idx_type;
3347 if (state->index_format == WINED3DFMT_R16_UINT)
3348 idx_type = VK_INDEX_TYPE_UINT16;
3349 else
3350 idx_type = VK_INDEX_TYPE_UINT32;
3351 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3352 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3353 wined3d_context_vk_reference_bo(context_vk, &buffer_vk->bo);
3354 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3355 buffer_info->offset + state->index_offset, idx_type));
3358 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3359 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3360 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3361 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3362 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3363 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3364 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3365 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3366 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3367 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3368 context_vk->c.update_shader_resource_bindings = 1;
3369 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3370 context_vk->c.update_unordered_access_view_bindings = 1;
3372 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3374 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3376 ERR("Failed to update shader descriptors.\n");
3377 return VK_NULL_HANDLE;
3380 context_vk->c.update_shader_resource_bindings = 0;
3381 context_vk->c.update_unordered_access_view_bindings = 0;
3384 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3385 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3387 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3388 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3390 return vk_command_buffer;
3393 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3394 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3396 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3397 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3398 VkCommandBuffer vk_command_buffer;
3400 wined3d_context_vk_end_current_render_pass(context_vk);
3402 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3403 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3405 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3407 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3408 if (!context_vk->compute.vk_pipeline)
3410 ERR("No compute pipeline set.\n");
3411 return VK_NULL_HANDLE;
3413 context_vk->c.update_compute_shader_resource_bindings = 1;
3414 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3415 context_vk->update_compute_pipeline = 1;
3418 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3420 if (indirect_vk)
3422 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3423 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3426 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3428 ERR("Failed to get command buffer.\n");
3429 return VK_NULL_HANDLE;
3432 if (context_vk->update_compute_pipeline)
3434 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3435 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3436 context_vk->update_compute_pipeline = 0;
3439 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3440 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3441 context_vk->c.update_compute_shader_resource_bindings = 1;
3442 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3443 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3445 if (context_vk->c.update_compute_shader_resource_bindings
3446 || context_vk->c.update_compute_unordered_access_view_bindings)
3448 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3450 ERR("Failed to update shader descriptors.\n");
3451 return VK_NULL_HANDLE;
3454 context_vk->c.update_compute_shader_resource_bindings = 0;
3455 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3458 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3459 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3461 return vk_command_buffer;
3464 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3466 VkCommandPoolCreateInfo command_pool_info;
3467 const struct wined3d_vk_info *vk_info;
3468 struct wined3d_adapter_vk *adapter_vk;
3469 struct wined3d_device_vk *device_vk;
3470 VkResult vr;
3472 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3474 memset(context_vk, 0, sizeof(*context_vk));
3475 wined3d_context_init(&context_vk->c, swapchain);
3476 device_vk = wined3d_device_vk(swapchain->device);
3477 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3478 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3480 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3481 command_pool_info.pNext = NULL;
3482 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT;
3483 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3484 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3485 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3487 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3488 wined3d_context_cleanup(&context_vk->c);
3489 return E_FAIL;
3491 context_vk->current_command_buffer.id = 1;
3493 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3495 list_init(&context_vk->render_pass_queries);
3496 list_init(&context_vk->active_queries);
3497 list_init(&context_vk->completed_query_pools);
3498 list_init(&context_vk->free_occlusion_query_pools);
3499 list_init(&context_vk->free_timestamp_query_pools);
3500 list_init(&context_vk->free_pipeline_statistics_query_pools);
3501 list_init(&context_vk->free_stream_output_statistics_query_pools);
3503 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3504 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3505 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3506 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3508 return WINED3D_OK;