wined3d: Introduce a wined3d_state_get_ffp_texture() helper.
[wine.git] / dlls / wined3d / context_vk.c
blob29a4a4998d49dd93f3fc640437e18eadb392e097
1 /*
2 * Copyright 2002-2004 Jason Edmeades
3 * Copyright 2002-2004 Raphael Junqueira
4 * Copyright 2004 Christian Costa
5 * Copyright 2005 Oliver Stieber
6 * Copyright 2006, 2008 Henri Verbeet
7 * Copyright 2007-2011, 2013 Stefan Dösinger for CodeWeavers
8 * Copyright 2009-2020 Henri Verbeet for CodeWeavers
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
25 #include "wined3d_private.h"
26 #include "wined3d_vk.h"
28 WINE_DEFAULT_DEBUG_CHANNEL(d3d);
30 VkCompareOp vk_compare_op_from_wined3d(enum wined3d_cmp_func op)
32 switch (op)
34 case WINED3D_CMP_NEVER:
35 return VK_COMPARE_OP_NEVER;
36 case WINED3D_CMP_LESS:
37 return VK_COMPARE_OP_LESS;
38 case WINED3D_CMP_EQUAL:
39 return VK_COMPARE_OP_EQUAL;
40 case WINED3D_CMP_LESSEQUAL:
41 return VK_COMPARE_OP_LESS_OR_EQUAL;
42 case WINED3D_CMP_GREATER:
43 return VK_COMPARE_OP_GREATER;
44 case WINED3D_CMP_NOTEQUAL:
45 return VK_COMPARE_OP_NOT_EQUAL;
46 case WINED3D_CMP_GREATEREQUAL:
47 return VK_COMPARE_OP_GREATER_OR_EQUAL;
48 case WINED3D_CMP_ALWAYS:
49 return VK_COMPARE_OP_ALWAYS;
50 default:
51 if (!op)
52 WARN("Unhandled compare operation %#x.\n", op);
53 else
54 FIXME("Unhandled compare operation %#x.\n", op);
55 return VK_COMPARE_OP_NEVER;
59 VkShaderStageFlagBits vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type)
61 switch (shader_type)
63 case WINED3D_SHADER_TYPE_VERTEX:
64 return VK_SHADER_STAGE_VERTEX_BIT;
65 case WINED3D_SHADER_TYPE_HULL:
66 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT;
67 case WINED3D_SHADER_TYPE_DOMAIN:
68 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT;
69 case WINED3D_SHADER_TYPE_GEOMETRY:
70 return VK_SHADER_STAGE_GEOMETRY_BIT;
71 case WINED3D_SHADER_TYPE_PIXEL:
72 return VK_SHADER_STAGE_FRAGMENT_BIT;
73 case WINED3D_SHADER_TYPE_COMPUTE:
74 return VK_SHADER_STAGE_COMPUTE_BIT;
75 default:
76 ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type));
77 return 0;
81 static VkBlendFactor vk_blend_factor_from_wined3d(enum wined3d_blend blend,
82 const struct wined3d_format *dst_format, bool alpha)
84 switch (blend)
86 case WINED3D_BLEND_ZERO:
87 return VK_BLEND_FACTOR_ZERO;
88 case WINED3D_BLEND_ONE:
89 return VK_BLEND_FACTOR_ONE;
90 case WINED3D_BLEND_SRCCOLOR:
91 return VK_BLEND_FACTOR_SRC_COLOR;
92 case WINED3D_BLEND_INVSRCCOLOR:
93 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR;
94 case WINED3D_BLEND_SRCALPHA:
95 return VK_BLEND_FACTOR_SRC_ALPHA;
96 case WINED3D_BLEND_INVSRCALPHA:
97 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
98 case WINED3D_BLEND_DESTALPHA:
99 if (dst_format->alpha_size)
100 return VK_BLEND_FACTOR_DST_ALPHA;
101 return VK_BLEND_FACTOR_ONE;
102 case WINED3D_BLEND_INVDESTALPHA:
103 if (dst_format->alpha_size)
104 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA;
105 return VK_BLEND_FACTOR_ZERO;
106 case WINED3D_BLEND_DESTCOLOR:
107 return VK_BLEND_FACTOR_DST_COLOR;
108 case WINED3D_BLEND_INVDESTCOLOR:
109 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR;
110 case WINED3D_BLEND_SRCALPHASAT:
111 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE;
112 case WINED3D_BLEND_BLENDFACTOR:
113 if (alpha)
114 return VK_BLEND_FACTOR_CONSTANT_ALPHA;
115 return VK_BLEND_FACTOR_CONSTANT_COLOR;
116 case WINED3D_BLEND_INVBLENDFACTOR:
117 if (alpha)
118 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA;
119 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR;
120 case WINED3D_BLEND_SRC1COLOR:
121 return VK_BLEND_FACTOR_SRC1_COLOR;
122 case WINED3D_BLEND_INVSRC1COLOR:
123 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR;
124 case WINED3D_BLEND_SRC1ALPHA:
125 return VK_BLEND_FACTOR_SRC1_ALPHA;
126 case WINED3D_BLEND_INVSRC1ALPHA:
127 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA;
128 default:
129 FIXME("Unhandled blend %#x.\n", blend);
130 return VK_BLEND_FACTOR_ZERO;
134 static VkBlendOp vk_blend_op_from_wined3d(enum wined3d_blend_op op)
136 switch (op)
138 case WINED3D_BLEND_OP_ADD:
139 return VK_BLEND_OP_ADD;
140 case WINED3D_BLEND_OP_SUBTRACT:
141 return VK_BLEND_OP_SUBTRACT;
142 case WINED3D_BLEND_OP_REVSUBTRACT:
143 return VK_BLEND_OP_REVERSE_SUBTRACT;
144 case WINED3D_BLEND_OP_MIN:
145 return VK_BLEND_OP_MIN;
146 case WINED3D_BLEND_OP_MAX:
147 return VK_BLEND_OP_MAX;
148 default:
149 FIXME("Unhandled blend op %#x.\n", op);
150 return VK_BLEND_OP_ADD;
154 static VkColorComponentFlags vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask)
156 VkColorComponentFlags vk_mask = 0;
158 if (wined3d_mask & WINED3DCOLORWRITEENABLE_RED)
159 vk_mask |= VK_COLOR_COMPONENT_R_BIT;
160 if (wined3d_mask & WINED3DCOLORWRITEENABLE_GREEN)
161 vk_mask |= VK_COLOR_COMPONENT_G_BIT;
162 if (wined3d_mask & WINED3DCOLORWRITEENABLE_BLUE)
163 vk_mask |= VK_COLOR_COMPONENT_B_BIT;
164 if (wined3d_mask & WINED3DCOLORWRITEENABLE_ALPHA)
165 vk_mask |= VK_COLOR_COMPONENT_A_BIT;
167 return vk_mask;
170 static VkCullModeFlags vk_cull_mode_from_wined3d(enum wined3d_cull mode)
172 switch (mode)
174 case WINED3D_CULL_NONE:
175 return VK_CULL_MODE_NONE;
176 case WINED3D_CULL_FRONT:
177 return VK_CULL_MODE_FRONT_BIT;
178 case WINED3D_CULL_BACK:
179 return VK_CULL_MODE_BACK_BIT;
180 default:
181 FIXME("Unhandled cull mode %#x.\n", mode);
182 return VK_CULL_MODE_NONE;
186 static VkPrimitiveTopology vk_topology_from_wined3d(enum wined3d_primitive_type t)
188 switch (t)
190 case WINED3D_PT_POINTLIST:
191 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
192 case WINED3D_PT_LINELIST:
193 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST;
194 case WINED3D_PT_LINESTRIP:
195 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP;
196 case WINED3D_PT_TRIANGLELIST:
197 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST;
198 case WINED3D_PT_TRIANGLESTRIP:
199 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
200 case WINED3D_PT_TRIANGLEFAN:
201 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
202 case WINED3D_PT_LINELIST_ADJ:
203 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY;
204 case WINED3D_PT_LINESTRIP_ADJ:
205 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY;
206 case WINED3D_PT_TRIANGLELIST_ADJ:
207 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY;
208 case WINED3D_PT_TRIANGLESTRIP_ADJ:
209 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
210 case WINED3D_PT_PATCH:
211 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST;
212 default:
213 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t));
214 case WINED3D_PT_UNDEFINED:
215 return ~0u;
219 static VkStencilOp vk_stencil_op_from_wined3d(enum wined3d_stencil_op op)
221 switch (op)
223 case WINED3D_STENCIL_OP_KEEP:
224 return VK_STENCIL_OP_KEEP;
225 case WINED3D_STENCIL_OP_ZERO:
226 return VK_STENCIL_OP_ZERO;
227 case WINED3D_STENCIL_OP_REPLACE:
228 return VK_STENCIL_OP_REPLACE;
229 case WINED3D_STENCIL_OP_INCR_SAT:
230 return VK_STENCIL_OP_INCREMENT_AND_CLAMP;
231 case WINED3D_STENCIL_OP_DECR_SAT:
232 return VK_STENCIL_OP_DECREMENT_AND_CLAMP;
233 case WINED3D_STENCIL_OP_INVERT:
234 return VK_STENCIL_OP_INVERT;
235 case WINED3D_STENCIL_OP_INCR:
236 return VK_STENCIL_OP_INCREMENT_AND_WRAP;
237 case WINED3D_STENCIL_OP_DECR:
238 return VK_STENCIL_OP_DECREMENT_AND_WRAP;
239 default:
240 if (!op)
241 WARN("Unhandled stencil operation %#x.\n", op);
242 else
243 FIXME("Unhandled stencil operation %#x.\n", op);
244 return VK_STENCIL_OP_KEEP;
248 static bool wined3d_get_unused_stream_index(const struct wined3d_state *state, uint32_t *index)
250 uint32_t i;
252 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
254 if (!state->streams[i].buffer)
256 *index = i;
257 return true;
261 return false;
264 static void wined3d_allocator_chunk_vk_lock(struct wined3d_allocator_chunk_vk *chunk_vk)
266 wined3d_device_vk_allocator_lock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
269 static void wined3d_allocator_chunk_vk_unlock(struct wined3d_allocator_chunk_vk *chunk_vk)
271 wined3d_device_vk_allocator_unlock(wined3d_device_vk_from_allocator(chunk_vk->c.allocator));
274 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk *chunk_vk,
275 struct wined3d_context_vk *context_vk)
277 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
278 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
279 void *map_ptr;
280 VkResult vr;
282 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk,
283 wine_dbgstr_longlong(chunk_vk->vk_memory), chunk_vk->c.map_ptr);
285 wined3d_allocator_chunk_vk_lock(chunk_vk);
287 if (!chunk_vk->c.map_ptr)
289 if ((vr = VK_CALL(vkMapMemory(device_vk->vk_device,
290 chunk_vk->vk_memory, 0, VK_WHOLE_SIZE, 0, &chunk_vk->c.map_ptr))) < 0)
292 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr));
293 wined3d_allocator_chunk_vk_unlock(chunk_vk);
294 return NULL;
297 adapter_adjust_mapped_memory(device_vk->d.adapter, WINED3D_ALLOCATOR_CHUNK_SIZE);
300 ++chunk_vk->c.map_count;
301 map_ptr = chunk_vk->c.map_ptr;
303 wined3d_allocator_chunk_vk_unlock(chunk_vk);
305 return map_ptr;
308 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk *chunk_vk,
309 struct wined3d_context_vk *context_vk)
311 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
312 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
314 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk, context_vk);
316 wined3d_allocator_chunk_vk_lock(chunk_vk);
318 if (--chunk_vk->c.map_count)
320 wined3d_allocator_chunk_vk_unlock(chunk_vk);
321 return;
324 VK_CALL(vkUnmapMemory(device_vk->vk_device, chunk_vk->vk_memory));
325 chunk_vk->c.map_ptr = NULL;
327 wined3d_allocator_chunk_vk_unlock(chunk_vk);
329 adapter_adjust_mapped_memory(device_vk->d.adapter, -WINED3D_ALLOCATOR_CHUNK_SIZE);
332 VkDeviceMemory wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk *context_vk,
333 unsigned int pool, size_t size)
335 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
336 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
337 VkMemoryAllocateInfo allocate_info;
338 VkDeviceMemory vk_memory;
339 VkResult vr;
341 allocate_info.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
342 allocate_info.pNext = NULL;
343 allocate_info.allocationSize = size;
344 allocate_info.memoryTypeIndex = pool;
345 if ((vr = VK_CALL(vkAllocateMemory(device_vk->vk_device, &allocate_info, NULL, &vk_memory))) < 0)
347 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr));
348 return VK_NULL_HANDLE;
351 return vk_memory;
354 static struct wined3d_allocator_block *wined3d_context_vk_allocate_memory(struct wined3d_context_vk *context_vk,
355 unsigned int memory_type, VkDeviceSize size, VkDeviceMemory *vk_memory)
357 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
358 struct wined3d_allocator *allocator = &device_vk->allocator;
359 struct wined3d_allocator_block *block;
361 wined3d_device_vk_allocator_lock(device_vk);
363 if (size > WINED3D_ALLOCATOR_CHUNK_SIZE / 2)
365 *vk_memory = wined3d_context_vk_allocate_vram_chunk_memory(context_vk, memory_type, size);
366 wined3d_device_vk_allocator_unlock(device_vk);
367 return NULL;
370 if (!(block = wined3d_allocator_allocate(allocator, &context_vk->c, memory_type, size)))
372 wined3d_device_vk_allocator_unlock(device_vk);
373 *vk_memory = VK_NULL_HANDLE;
374 return NULL;
377 *vk_memory = wined3d_allocator_chunk_vk(block->chunk)->vk_memory;
379 wined3d_device_vk_allocator_unlock(device_vk);
380 return block;
383 static void wined3d_context_vk_free_memory(struct wined3d_context_vk *context_vk, struct wined3d_allocator_block *block)
385 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
387 assert(block->chunk->allocator == &device_vk->allocator);
388 wined3d_device_vk_allocator_lock(device_vk);
389 wined3d_allocator_block_free(block);
390 wined3d_device_vk_allocator_unlock(device_vk);
393 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk *context_vk,
394 VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
396 const struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
397 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
398 const VkPhysicalDeviceLimits *limits = &adapter_vk->device_limits;
399 struct wined3d_bo_slab_vk_key key;
400 struct wined3d_bo_slab_vk *slab;
401 struct wine_rb_entry *entry;
402 size_t object_size, idx;
403 size_t alignment;
405 if (size > WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 2)
406 return false;
408 alignment = WINED3D_SLAB_BO_MIN_OBJECT_ALIGN;
409 if ((usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT))
410 && limits->minTexelBufferOffsetAlignment > alignment)
411 alignment = limits->minTexelBufferOffsetAlignment;
412 if ((usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) && limits->minUniformBufferOffsetAlignment)
413 alignment = limits->minUniformBufferOffsetAlignment;
414 if ((usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) && limits->minStorageBufferOffsetAlignment)
415 alignment = limits->minStorageBufferOffsetAlignment;
417 object_size = (size + (alignment - 1)) & ~(alignment - 1);
418 if (object_size < WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32)
419 object_size = WINED3D_ALLOCATOR_MIN_BLOCK_SIZE / 32;
420 key.memory_type = memory_type;
421 key.usage = usage;
422 key.size = 32 * object_size;
424 wined3d_device_vk_allocator_lock(device_vk);
426 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
428 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
429 TRACE("Using existing bo slab %p.\n", slab);
431 else
433 if (!(slab = heap_alloc_zero(sizeof(*slab))))
435 wined3d_device_vk_allocator_unlock(device_vk);
436 ERR("Failed to allocate bo slab.\n");
437 return false;
440 if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
442 wined3d_device_vk_allocator_unlock(device_vk);
443 ERR("Failed to add slab to available tree.\n");
444 heap_free(slab);
445 return false;
448 slab->requested_memory_type = memory_type;
449 if (!wined3d_context_vk_create_bo(context_vk, key.size, usage, memory_type, &slab->bo))
451 wined3d_device_vk_allocator_unlock(device_vk);
452 ERR("Failed to create slab bo.\n");
453 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
454 heap_free(slab);
455 return false;
457 slab->map = ~0u;
459 TRACE("Created new bo slab %p.\n", slab);
462 idx = wined3d_bit_scan(&slab->map);
463 if (!slab->map)
465 if (slab->next)
467 wine_rb_replace(&context_vk->bo_slab_available, &slab->entry, &slab->next->entry);
468 slab->next = NULL;
470 else
472 wine_rb_remove(&context_vk->bo_slab_available, &slab->entry);
476 wined3d_device_vk_allocator_unlock(device_vk);
478 *bo = slab->bo;
479 bo->memory = NULL;
480 bo->slab = slab;
481 bo->b.refcount = 1;
482 bo->b.client_map_count = 0;
483 bo->b.map_ptr = NULL;
484 bo->b.buffer_offset = idx * object_size;
485 bo->b.memory_offset = slab->bo.b.memory_offset + bo->b.buffer_offset;
486 bo->size = size;
487 list_init(&bo->b.users);
488 bo->command_buffer_id = 0;
489 bo->host_synced = false;
491 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
492 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory),
493 wine_dbgstr_longlong(bo->b.buffer_offset), bo);
495 return true;
498 BOOL wined3d_context_vk_create_bo(struct wined3d_context_vk *context_vk, VkDeviceSize size,
499 VkBufferUsageFlags usage, VkMemoryPropertyFlags memory_type, struct wined3d_bo_vk *bo)
501 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
502 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
503 VkMemoryRequirements memory_requirements;
504 struct wined3d_adapter_vk *adapter_vk;
505 VkBufferCreateInfo create_info;
506 unsigned int memory_type_idx;
507 VkResult vr;
509 if (wined3d_context_vk_create_slab_bo(context_vk, size, usage, memory_type, bo))
510 return TRUE;
512 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
514 create_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
515 create_info.pNext = NULL;
516 create_info.flags = 0;
517 create_info.size = size;
518 create_info.usage = usage;
519 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
520 create_info.queueFamilyIndexCount = 0;
521 create_info.pQueueFamilyIndices = NULL;
523 if ((vr = VK_CALL(vkCreateBuffer(device_vk->vk_device, &create_info, NULL, &bo->vk_buffer))) < 0)
525 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr));
526 return FALSE;
529 VK_CALL(vkGetBufferMemoryRequirements(device_vk->vk_device, bo->vk_buffer, &memory_requirements));
531 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
532 memory_requirements.memoryTypeBits, memory_type);
533 if (memory_type_idx == ~0u)
535 ERR("Failed to find suitable memory type.\n");
536 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
537 return FALSE;
539 bo->memory = wined3d_context_vk_allocate_memory(context_vk,
540 memory_type_idx, memory_requirements.size, &bo->vk_memory);
541 if (!bo->vk_memory)
543 ERR("Failed to allocate buffer memory.\n");
544 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
545 return FALSE;
547 bo->b.memory_offset = bo->memory ? bo->memory->offset : 0;
549 if ((vr = VK_CALL(vkBindBufferMemory(device_vk->vk_device, bo->vk_buffer,
550 bo->vk_memory, bo->b.memory_offset))) < 0)
552 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr));
553 if (bo->memory)
554 wined3d_context_vk_free_memory(context_vk, bo->memory);
555 else
556 VK_CALL(vkFreeMemory(device_vk->vk_device, bo->vk_memory, NULL));
557 VK_CALL(vkDestroyBuffer(device_vk->vk_device, bo->vk_buffer, NULL));
558 return FALSE;
561 bo->b.refcount = 1;
562 bo->b.client_map_count = 0;
563 bo->b.map_ptr = NULL;
564 bo->b.buffer_offset = 0;
565 bo->size = size;
566 bo->usage = usage;
567 bo->memory_type = adapter_vk->memory_properties.memoryTypes[memory_type_idx].propertyFlags;
568 bo->b.coherent = !!(bo->memory_type & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
569 list_init(&bo->b.users);
570 bo->command_buffer_id = 0;
571 bo->slab = NULL;
572 bo->host_synced = false;
574 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
575 wine_dbgstr_longlong(bo->vk_buffer), wine_dbgstr_longlong(bo->vk_memory), bo);
577 return TRUE;
580 BOOL wined3d_context_vk_create_image(struct wined3d_context_vk *context_vk, VkImageType vk_image_type,
581 VkImageUsageFlags usage, VkFormat vk_format, unsigned int width, unsigned int height, unsigned int depth,
582 unsigned int sample_count, unsigned int mip_levels, unsigned int layer_count, unsigned int flags,
583 struct wined3d_image_vk *image)
585 struct wined3d_adapter_vk *adapter_vk = wined3d_adapter_vk(context_vk->c.device->adapter);
586 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
587 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
588 VkMemoryRequirements memory_requirements;
589 VkImageCreateInfo create_info;
590 unsigned int memory_type_idx;
591 VkResult vr;
593 create_info.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
594 create_info.pNext = NULL;
595 create_info.flags = flags;
596 create_info.imageType = vk_image_type;
597 create_info.format = vk_format;
598 create_info.extent.width = width;
599 create_info.extent.height = height;
600 create_info.extent.depth = depth;
601 create_info.mipLevels = mip_levels;
602 create_info.arrayLayers = layer_count;
603 create_info.samples = sample_count;
604 create_info.tiling = VK_IMAGE_TILING_OPTIMAL;
605 create_info.usage = usage;
606 create_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
607 create_info.queueFamilyIndexCount = 0;
608 create_info.pQueueFamilyIndices = NULL;
609 create_info.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED;
611 image->command_buffer_id = 0;
613 vr = VK_CALL(vkCreateImage(device_vk->vk_device, &create_info, NULL, &image->vk_image));
614 if (vr != VK_SUCCESS)
616 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr));
617 image->vk_image = VK_NULL_HANDLE;
618 return FALSE;
621 VK_CALL(vkGetImageMemoryRequirements(device_vk->vk_device, image->vk_image,
622 &memory_requirements));
624 memory_type_idx = wined3d_adapter_vk_get_memory_type_index(adapter_vk,
625 memory_requirements.memoryTypeBits, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
626 if (memory_type_idx == ~0u)
628 ERR("Failed to find suitable image memory type.\n");
629 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
630 image->vk_image = VK_NULL_HANDLE;
631 return FALSE;
634 image->memory = wined3d_context_vk_allocate_memory(context_vk, memory_type_idx,
635 memory_requirements.size, &image->vk_memory);
636 if (!image->vk_memory)
638 ERR("Failed to allocate image memory.\n");
639 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
640 image->vk_image = VK_NULL_HANDLE;
641 return FALSE;
644 vr = VK_CALL(vkBindImageMemory(device_vk->vk_device, image->vk_image, image->vk_memory,
645 image->memory ? image->memory->offset : 0));
646 if (vr != VK_SUCCESS)
648 VK_CALL(vkDestroyImage(device_vk->vk_device, image->vk_image, NULL));
649 if (image->memory)
650 wined3d_context_vk_free_memory(context_vk, image->memory);
651 else
652 VK_CALL(vkFreeMemory(device_vk->vk_device, image->vk_memory, NULL));
653 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr));
654 image->memory = NULL;
655 image->vk_memory = VK_NULL_HANDLE;
656 image->vk_image = VK_NULL_HANDLE;
657 return FALSE;
660 return TRUE;
663 static struct wined3d_retired_object_vk *wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk *context_vk)
665 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
666 struct wined3d_retired_object_vk *o;
668 if (retired->free)
670 o = retired->free;
671 retired->free = o->u.next;
672 return o;
675 if (!wined3d_array_reserve((void **)&retired->objects, &retired->size,
676 retired->count + 1, sizeof(*retired->objects)))
677 return NULL;
679 return &retired->objects[retired->count++];
682 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk *context_vk,
683 VkFramebuffer vk_framebuffer, uint64_t command_buffer_id)
685 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
686 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
687 struct wined3d_retired_object_vk *o;
689 if (context_vk->completed_command_buffer_id >= command_buffer_id)
691 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, vk_framebuffer, NULL));
692 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
693 return;
696 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
698 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer));
699 return;
702 o->type = WINED3D_RETIRED_FRAMEBUFFER_VK;
703 o->u.vk_framebuffer = vk_framebuffer;
704 o->command_buffer_id = command_buffer_id;
707 static void wined3d_context_vk_return_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
708 VkDescriptorPool vk_descriptor_pool)
710 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
711 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
713 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
714 context_vk->vk_descriptor_pool_count + 1, sizeof(*context_vk->vk_descriptor_pools)))
716 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, vk_descriptor_pool, NULL));
717 TRACE("Destroying descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
718 return;
721 VK_CALL(vkResetDescriptorPool(device_vk->vk_device, vk_descriptor_pool, 0));
722 context_vk->vk_descriptor_pools[context_vk->vk_descriptor_pool_count++] = vk_descriptor_pool;
725 static void wined3d_context_vk_reset_vk_descriptor_pool(struct wined3d_context_vk *context_vk,
726 VkDescriptorPool vk_descriptor_pool, uint64_t command_buffer_id)
728 struct wined3d_retired_object_vk *o;
730 if (context_vk->completed_command_buffer_id >= command_buffer_id)
732 wined3d_context_vk_return_vk_descriptor_pool(context_vk, vk_descriptor_pool);
733 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
734 return;
737 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
739 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool));
740 return;
743 o->type = WINED3D_RETIRED_DESCRIPTOR_POOL_VK;
744 o->u.vk_descriptor_pool = vk_descriptor_pool;
745 o->command_buffer_id = command_buffer_id;
748 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk *context_vk,
749 VkDeviceMemory vk_memory, uint64_t command_buffer_id)
751 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
752 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
753 struct wined3d_retired_object_vk *o;
755 if (context_vk->completed_command_buffer_id >= command_buffer_id)
757 VK_CALL(vkFreeMemory(device_vk->vk_device, vk_memory, NULL));
758 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
759 return;
762 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
764 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory));
765 return;
768 o->type = WINED3D_RETIRED_MEMORY_VK;
769 o->u.vk_memory = vk_memory;
770 o->command_buffer_id = command_buffer_id;
773 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk *context_vk,
774 struct wined3d_allocator_block *block, uint64_t command_buffer_id)
776 struct wined3d_retired_object_vk *o;
778 if (context_vk->completed_command_buffer_id >= command_buffer_id)
780 wined3d_context_vk_free_memory(context_vk, block);
781 TRACE("Freed block %p.\n", block);
782 return;
785 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
787 ERR("Leaking block %p.\n", block);
788 return;
791 o->type = WINED3D_RETIRED_ALLOCATOR_BLOCK_VK;
792 o->u.block = block;
793 o->command_buffer_id = command_buffer_id;
796 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk *slab,
797 SIZE_T idx, struct wined3d_context_vk *context_vk)
799 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
800 struct wined3d_bo_slab_vk_key key;
801 struct wine_rb_entry *entry;
803 TRACE("slab %p, idx %Iu, context_vk %p.\n", slab, idx, context_vk);
805 wined3d_device_vk_allocator_lock(device_vk);
807 if (!slab->map)
809 key.memory_type = slab->requested_memory_type;
810 key.usage = slab->bo.usage;
811 key.size = slab->bo.size;
813 if ((entry = wine_rb_get(&context_vk->bo_slab_available, &key)))
815 slab->next = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
816 wine_rb_replace(&context_vk->bo_slab_available, entry, &slab->entry);
818 else if (wine_rb_put(&context_vk->bo_slab_available, &key, &slab->entry) < 0)
820 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab, slab->map);
823 slab->map |= 1u << idx;
825 wined3d_device_vk_allocator_unlock(device_vk);
828 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk *context_vk,
829 struct wined3d_bo_slab_vk *slab, SIZE_T idx, uint64_t command_buffer_id)
831 struct wined3d_retired_object_vk *o;
833 if (context_vk->completed_command_buffer_id >= command_buffer_id)
835 wined3d_bo_slab_vk_free_slice(slab, idx, context_vk);
836 return;
839 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
841 ERR("Leaking slab %p, slice %#Ix.\n", slab, idx);
842 return;
845 o->type = WINED3D_RETIRED_BO_SLAB_SLICE_VK;
846 o->u.slice.slab = slab;
847 o->u.slice.idx = idx;
848 o->command_buffer_id = command_buffer_id;
851 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk *context_vk,
852 VkBuffer vk_buffer, uint64_t command_buffer_id)
854 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
855 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
856 struct wined3d_retired_object_vk *o;
858 if (context_vk->completed_command_buffer_id >= command_buffer_id)
860 VK_CALL(vkDestroyBuffer(device_vk->vk_device, vk_buffer, NULL));
861 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
862 return;
865 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
867 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer));
868 return;
871 o->type = WINED3D_RETIRED_BUFFER_VK;
872 o->u.vk_buffer = vk_buffer;
873 o->command_buffer_id = command_buffer_id;
876 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk *context_vk,
877 VkImage vk_image, uint64_t command_buffer_id)
879 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
880 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
881 struct wined3d_retired_object_vk *o;
883 if (context_vk->completed_command_buffer_id >= command_buffer_id)
885 VK_CALL(vkDestroyImage(device_vk->vk_device, vk_image, NULL));
886 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image));
887 return;
890 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
892 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image));
893 return;
896 o->type = WINED3D_RETIRED_IMAGE_VK;
897 o->u.vk_image = vk_image;
898 o->command_buffer_id = command_buffer_id;
901 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk *context_vk,
902 VkBufferView vk_view, uint64_t command_buffer_id)
904 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
905 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
906 struct wined3d_retired_object_vk *o;
908 if (context_vk->completed_command_buffer_id >= command_buffer_id)
910 VK_CALL(vkDestroyBufferView(device_vk->vk_device, vk_view, NULL));
911 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
912 return;
915 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
917 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view));
918 return;
921 o->type = WINED3D_RETIRED_BUFFER_VIEW_VK;
922 o->u.vk_buffer_view = vk_view;
923 o->command_buffer_id = command_buffer_id;
926 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk *context_vk,
927 VkImageView vk_view, uint64_t command_buffer_id)
929 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
930 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
931 struct wined3d_retired_object_vk *o;
933 if (context_vk->completed_command_buffer_id >= command_buffer_id)
935 VK_CALL(vkDestroyImageView(device_vk->vk_device, vk_view, NULL));
936 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
937 return;
940 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
942 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view));
943 return;
946 o->type = WINED3D_RETIRED_IMAGE_VIEW_VK;
947 o->u.vk_image_view = vk_view;
948 o->command_buffer_id = command_buffer_id;
951 static void wined3d_context_vk_reset_completed_queries(struct wined3d_context_vk *context_vk,
952 struct wined3d_query_pool_vk *pool_vk, struct wined3d_command_buffer_vk *buffer)
954 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
955 struct wined3d_retired_object_vk *o;
956 struct wined3d_range range;
957 unsigned int start = 0;
959 for (;;)
961 if (!wined3d_bitmap_get_range(pool_vk->completed, WINED3D_QUERY_POOL_SIZE, start, &range))
962 break;
964 VK_CALL(vkCmdResetQueryPool(buffer->vk_command_buffer, pool_vk->vk_query_pool, range.offset, range.size));
966 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
968 ERR("Freeing query range %u+%u in pool %p.\n", range.offset, range.size, pool_vk);
969 wined3d_query_pool_vk_mark_free(context_vk, pool_vk, range.offset, range.size);
971 else
973 o->type = WINED3D_RETIRED_QUERY_POOL_VK;
974 o->u.queries.pool_vk = pool_vk;
975 o->u.queries.start = range.offset;
976 o->u.queries.count = range.size;
977 o->command_buffer_id = buffer->id;
980 start = range.offset + range.size;
983 memset(pool_vk->completed, 0, sizeof(pool_vk->completed));
986 void wined3d_context_vk_destroy_vk_pipeline(struct wined3d_context_vk *context_vk,
987 VkPipeline vk_pipeline, uint64_t command_buffer_id)
989 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
990 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
991 struct wined3d_retired_object_vk *o;
993 if (context_vk->completed_command_buffer_id >= command_buffer_id)
995 VK_CALL(vkDestroyPipeline(device_vk->vk_device, vk_pipeline, NULL));
996 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
997 return;
1000 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1002 ERR("Leaking pipeline 0x%s.\n", wine_dbgstr_longlong(vk_pipeline));
1003 return;
1006 o->type = WINED3D_RETIRED_PIPELINE_VK;
1007 o->u.vk_pipeline = vk_pipeline;
1008 o->command_buffer_id = command_buffer_id;
1012 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk *context_vk,
1013 VkSampler vk_sampler, uint64_t command_buffer_id)
1015 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1016 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1017 struct wined3d_retired_object_vk *o;
1019 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1021 VK_CALL(vkDestroySampler(device_vk->vk_device, vk_sampler, NULL));
1022 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1023 return;
1026 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1028 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler));
1029 return;
1032 o->type = WINED3D_RETIRED_SAMPLER_VK;
1033 o->u.vk_sampler = vk_sampler;
1034 o->command_buffer_id = command_buffer_id;
1037 void wined3d_context_vk_destroy_vk_event(struct wined3d_context_vk *context_vk,
1038 VkEvent vk_event, uint64_t command_buffer_id)
1040 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1041 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1042 struct wined3d_retired_object_vk *o;
1044 if (context_vk->completed_command_buffer_id >= command_buffer_id)
1046 VK_CALL(vkDestroyEvent(device_vk->vk_device, vk_event, NULL));
1047 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1048 return;
1051 if (!(o = wined3d_context_vk_get_retired_object_vk(context_vk)))
1053 ERR("Leaking event 0x%s.\n", wine_dbgstr_longlong(vk_event));
1054 return;
1057 o->type = WINED3D_RETIRED_EVENT_VK;
1058 o->u.vk_event = vk_event;
1059 o->command_buffer_id = command_buffer_id;
1062 void wined3d_context_vk_destroy_image(struct wined3d_context_vk *context_vk, struct wined3d_image_vk *image)
1064 wined3d_context_vk_destroy_vk_image(context_vk, image->vk_image, image->command_buffer_id);
1065 if (image->memory)
1066 wined3d_context_vk_destroy_allocator_block(context_vk, image->memory,
1067 image->command_buffer_id);
1068 else
1069 wined3d_context_vk_destroy_vk_memory(context_vk, image->vk_memory, image->command_buffer_id);
1071 image->vk_image = VK_NULL_HANDLE;
1072 image->vk_memory = VK_NULL_HANDLE;
1073 image->memory = NULL;
1076 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk *context_vk, const struct wined3d_bo_vk *bo)
1078 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1079 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1080 struct wined3d_bo_slab_vk *slab_vk;
1081 size_t object_size, idx;
1083 TRACE("context_vk %p, bo %p.\n", context_vk, bo);
1085 assert(list_empty(&bo->b.users));
1087 if (bo->command_buffer_id == context_vk->current_command_buffer.id)
1088 context_vk->retired_bo_size += bo->size;
1090 if ((slab_vk = bo->slab))
1092 if (bo->b.map_ptr)
1093 wined3d_bo_slab_vk_unmap(slab_vk, context_vk);
1094 object_size = slab_vk->bo.size / 32;
1095 idx = bo->b.buffer_offset / object_size;
1096 wined3d_context_vk_destroy_bo_slab_slice(context_vk, slab_vk, idx, bo->command_buffer_id);
1097 return;
1100 wined3d_context_vk_destroy_vk_buffer(context_vk, bo->vk_buffer, bo->command_buffer_id);
1101 if (bo->memory)
1103 if (bo->b.map_ptr)
1104 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo->memory->chunk), context_vk);
1105 wined3d_context_vk_destroy_allocator_block(context_vk, bo->memory, bo->command_buffer_id);
1106 return;
1109 if (bo->b.map_ptr)
1111 VK_CALL(vkUnmapMemory(device_vk->vk_device, bo->vk_memory));
1112 adapter_adjust_mapped_memory(device_vk->d.adapter, -bo->size);
1114 wined3d_context_vk_destroy_vk_memory(context_vk, bo->vk_memory, bo->command_buffer_id);
1117 static void free_command_buffer(struct wined3d_context_vk *context_vk, struct wined3d_command_buffer_vk *buffer)
1119 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1120 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1122 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
1123 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device,
1124 context_vk->vk_command_pool, 1, &buffer->vk_command_buffer));
1127 static void wined3d_context_vk_remove_command_buffer(struct wined3d_context_vk *context_vk,
1128 unsigned int submit_index)
1130 struct wined3d_command_buffer_vk *buffer = &context_vk->submitted.buffers[submit_index];
1132 if (buffer->id > context_vk->completed_command_buffer_id)
1133 context_vk->completed_command_buffer_id = buffer->id;
1135 if (wined3d_array_reserve((void **)&context_vk->completed.buffers, &context_vk->completed.buffers_size,
1136 context_vk->completed.buffer_count + 1, sizeof(*context_vk->completed.buffers)))
1137 context_vk->completed.buffers[context_vk->completed.buffer_count++] = *buffer;
1138 else
1139 free_command_buffer(context_vk, buffer);
1141 *buffer = context_vk->submitted.buffers[--context_vk->submitted.buffer_count];
1144 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk *context_vk, VkFence vk_fence)
1146 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1147 struct wined3d_retired_objects_vk *retired = &context_vk->retired;
1148 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1149 struct wined3d_command_buffer_vk *buffer;
1150 struct wined3d_retired_object_vk *o;
1151 uint64_t command_buffer_id;
1152 SIZE_T i = 0;
1154 while (i < context_vk->submitted.buffer_count)
1156 buffer = &context_vk->submitted.buffers[i];
1157 if (VK_CALL(vkGetFenceStatus(device_vk->vk_device, buffer->vk_fence)) == VK_NOT_READY)
1159 ++i;
1160 continue;
1163 TRACE("Command buffer %p with id 0x%s has finished.\n",
1164 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1165 if (buffer->vk_fence == vk_fence)
1166 return;
1167 wined3d_context_vk_remove_command_buffer(context_vk, i);
1170 command_buffer_id = context_vk->completed_command_buffer_id;
1172 retired->free = NULL;
1173 for (i = retired->count; i; --i)
1175 o = &retired->objects[i - 1];
1177 if (o->type != WINED3D_RETIRED_FREE_VK && o->command_buffer_id > command_buffer_id)
1178 continue;
1180 switch (o->type)
1182 case WINED3D_RETIRED_FREE_VK:
1183 /* Nothing to do. */
1184 break;
1186 case WINED3D_RETIRED_FRAMEBUFFER_VK:
1187 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, o->u.vk_framebuffer, NULL));
1188 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_framebuffer));
1189 break;
1191 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK:
1192 wined3d_context_vk_return_vk_descriptor_pool(context_vk, o->u.vk_descriptor_pool);
1193 TRACE("Reset descriptor pool 0x%s.\n", wine_dbgstr_longlong(o->u.vk_descriptor_pool));
1194 break;
1196 case WINED3D_RETIRED_MEMORY_VK:
1197 VK_CALL(vkFreeMemory(device_vk->vk_device, o->u.vk_memory, NULL));
1198 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o->u.vk_memory));
1199 break;
1201 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK:
1202 TRACE("Destroying block %p.\n", o->u.block);
1203 wined3d_context_vk_free_memory(context_vk, o->u.block);
1204 break;
1206 case WINED3D_RETIRED_BO_SLAB_SLICE_VK:
1207 wined3d_bo_slab_vk_free_slice(o->u.slice.slab, o->u.slice.idx, context_vk);
1208 break;
1210 case WINED3D_RETIRED_BUFFER_VK:
1211 VK_CALL(vkDestroyBuffer(device_vk->vk_device, o->u.vk_buffer, NULL));
1212 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer));
1213 break;
1215 case WINED3D_RETIRED_IMAGE_VK:
1216 VK_CALL(vkDestroyImage(device_vk->vk_device, o->u.vk_image, NULL));
1217 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image));
1218 break;
1220 case WINED3D_RETIRED_BUFFER_VIEW_VK:
1221 VK_CALL(vkDestroyBufferView(device_vk->vk_device, o->u.vk_buffer_view, NULL));
1222 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_buffer_view));
1223 break;
1225 case WINED3D_RETIRED_IMAGE_VIEW_VK:
1226 VK_CALL(vkDestroyImageView(device_vk->vk_device, o->u.vk_image_view, NULL));
1227 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o->u.vk_image_view));
1228 break;
1230 case WINED3D_RETIRED_SAMPLER_VK:
1231 VK_CALL(vkDestroySampler(device_vk->vk_device, o->u.vk_sampler, NULL));
1232 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o->u.vk_sampler));
1233 break;
1235 case WINED3D_RETIRED_QUERY_POOL_VK:
1236 wined3d_query_pool_vk_mark_free(context_vk, o->u.queries.pool_vk, o->u.queries.start, o->u.queries.count);
1237 TRACE("Freed query range %u+%u in pool %p.\n", o->u.queries.start, o->u.queries.count, o->u.queries.pool_vk);
1238 break;
1240 case WINED3D_RETIRED_EVENT_VK:
1241 VK_CALL(vkDestroyEvent(device_vk->vk_device, o->u.vk_event, NULL));
1242 TRACE("Destroyed event 0x%s.\n", wine_dbgstr_longlong(o->u.vk_event));
1243 break;
1245 case WINED3D_RETIRED_PIPELINE_VK:
1246 VK_CALL(vkDestroyPipeline(device_vk->vk_device, o->u.vk_pipeline, NULL));
1247 TRACE("Destroyed pipeline 0x%s.\n", wine_dbgstr_longlong(o->u.vk_pipeline));
1248 break;
1250 default:
1251 ERR("Unhandled object type %#x.\n", o->type);
1252 break;
1255 if (i == retired->count)
1257 --retired->count;
1258 continue;
1261 o->type = WINED3D_RETIRED_FREE_VK;
1262 o->u.next = retired->free;
1263 retired->free = o;
1265 if (vk_fence && VK_CALL(vkGetFenceStatus(device_vk->vk_device, vk_fence)) != VK_NOT_READY)
1266 break;
1270 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry *entry, void *ctx)
1272 struct wined3d_context_vk *context_vk = ctx;
1273 struct wined3d_bo_slab_vk *slab, *next;
1275 slab = WINE_RB_ENTRY_VALUE(entry, struct wined3d_bo_slab_vk, entry);
1276 while (slab)
1278 next = slab->next;
1279 wined3d_context_vk_destroy_bo(context_vk, &slab->bo);
1280 heap_free(slab);
1281 slab = next;
1285 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry *entry, void *ctx)
1287 struct wined3d_graphics_pipeline_vk *pipeline_vk = WINE_RB_ENTRY_VALUE(entry,
1288 struct wined3d_graphics_pipeline_vk, entry);
1289 struct wined3d_context_vk *context_vk = ctx;
1290 const struct wined3d_vk_info *vk_info;
1291 struct wined3d_device_vk *device_vk;
1293 vk_info = context_vk->vk_info;
1294 device_vk = wined3d_device_vk(context_vk->c.device);
1296 VK_CALL(vkDestroyPipeline(device_vk->vk_device, pipeline_vk->vk_pipeline, NULL));
1297 heap_free(pipeline_vk);
1300 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry *entry, void *ctx)
1302 struct wined3d_pipeline_layout_vk *layout = WINE_RB_ENTRY_VALUE(entry,
1303 struct wined3d_pipeline_layout_vk, entry);
1304 struct wined3d_context_vk *context_vk = ctx;
1305 const struct wined3d_vk_info *vk_info;
1306 struct wined3d_device_vk *device_vk;
1308 vk_info = context_vk->vk_info;
1309 device_vk = wined3d_device_vk(context_vk->c.device);
1311 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
1312 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
1313 heap_free(layout->key.bindings);
1314 heap_free(layout);
1317 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk *key,
1318 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1320 struct wined3d_render_pass_attachment_vk *a;
1321 struct wined3d_rendertarget_view *view;
1322 unsigned int i;
1323 DWORD location;
1325 memset(key, 0, sizeof(*key));
1327 for (i = 0; i < rt_count; ++i)
1329 if (!(view = fb->render_targets[i]) || view->format->id == WINED3DFMT_NULL)
1330 continue;
1332 a = &key->rt[i];
1333 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1334 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1335 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1336 location = wined3d_rendertarget_view_get_locations(view);
1338 if (clear_flags & WINED3DCLEAR_TARGET)
1339 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1340 else if (location & WINED3D_LOCATION_DISCARDED)
1341 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1342 else if (location & WINED3D_LOCATION_CLEARED)
1343 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C;
1345 key->rt_mask |= 1u << i;
1348 if (depth_stencil && (view = fb->depth_stencil))
1350 a = &key->ds;
1351 a->vk_format = wined3d_format_vk(view->format)->vk_format;
1352 a->vk_samples = max(1, wined3d_resource_get_sample_count(view->resource));
1353 a->vk_layout = wined3d_texture_vk(wined3d_texture_from_resource(view->resource))->layout;
1354 location = wined3d_rendertarget_view_get_locations(view);
1355 key->rt_mask |= 1u << WINED3D_MAX_RENDER_TARGETS;
1357 if (clear_flags & WINED3DCLEAR_STENCIL)
1358 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S;
1359 if (clear_flags & WINED3DCLEAR_ZBUFFER)
1360 a->flags |= WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1362 if (!a->flags && (location & WINED3D_LOCATION_DISCARDED))
1363 a->flags = WINED3D_FB_ATTACHMENT_FLAG_DISCARDED;
1364 else if (location & WINED3D_LOCATION_CLEARED)
1365 a->flags = WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S | WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z;
1369 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk *pass,
1370 struct wined3d_context_vk *context_vk)
1372 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1373 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1375 VK_CALL(vkDestroyRenderPass(device_vk->vk_device, pass->vk_render_pass, NULL));
1378 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk *pass,
1379 struct wined3d_context_vk *context_vk, const struct wined3d_render_pass_key_vk *key)
1381 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1382 VkAttachmentReference attachment_references[WINED3D_MAX_RENDER_TARGETS];
1383 VkAttachmentDescription attachments[WINED3D_MAX_RENDER_TARGETS + 1];
1384 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1385 const struct wined3d_render_pass_attachment_vk *a;
1386 VkAttachmentReference ds_attachment_reference;
1387 VkAttachmentReference *ds_reference = NULL;
1388 unsigned int attachment_count, rt_count, i;
1389 VkAttachmentDescription *attachment;
1390 VkSubpassDescription sub_pass_desc;
1391 VkRenderPassCreateInfo pass_desc;
1392 uint32_t mask;
1393 VkResult vr;
1395 rt_count = 0;
1396 attachment_count = 0;
1397 mask = key->rt_mask & wined3d_mask_from_size(WINED3D_MAX_RENDER_TARGETS);
1398 while (mask)
1400 i = wined3d_bit_scan(&mask);
1401 a = &key->rt[i];
1403 attachment = &attachments[attachment_count];
1404 attachment->flags = 0;
1405 attachment->format = a->vk_format;
1406 attachment->samples = a->vk_samples;
1408 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1409 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1410 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_C)
1411 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1412 else
1413 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1415 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1416 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1417 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
1418 attachment->initialLayout = a->vk_layout;
1419 attachment->finalLayout = a->vk_layout;
1421 attachment_references[i].attachment = attachment_count;
1422 attachment_references[i].layout = a->vk_layout;
1424 ++attachment_count;
1425 rt_count = i + 1;
1428 mask = ~key->rt_mask & wined3d_mask_from_size(rt_count);
1429 while (mask)
1431 i = wined3d_bit_scan(&mask);
1432 attachment_references[i].attachment = VK_ATTACHMENT_UNUSED;
1433 attachment_references[i].layout = VK_IMAGE_LAYOUT_UNDEFINED;
1436 if (key->rt_mask & (1u << WINED3D_MAX_RENDER_TARGETS))
1438 a = &key->ds;
1440 attachment = &attachments[attachment_count];
1441 attachment->flags = 0;
1442 attachment->format = a->vk_format;
1443 attachment->samples = a->vk_samples;
1445 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1446 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1447 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_Z)
1448 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1449 else
1450 attachment->loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1452 if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_DISCARDED)
1453 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
1454 else if (a->flags & WINED3D_FB_ATTACHMENT_FLAG_CLEAR_S)
1455 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_CLEAR;
1456 else
1457 attachment->stencilLoadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
1459 attachment->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
1460 attachment->stencilStoreOp = VK_ATTACHMENT_STORE_OP_STORE;
1461 attachment->initialLayout = a->vk_layout;
1462 attachment->finalLayout = a->vk_layout;
1464 ds_reference = &ds_attachment_reference;
1465 ds_reference->attachment = attachment_count;
1466 ds_reference->layout = a->vk_layout;
1468 ++attachment_count;
1471 sub_pass_desc.flags = 0;
1472 sub_pass_desc.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS;
1473 sub_pass_desc.inputAttachmentCount = 0;
1474 sub_pass_desc.pInputAttachments = NULL;
1475 sub_pass_desc.colorAttachmentCount = rt_count;
1476 sub_pass_desc.pColorAttachments = attachment_references;
1477 sub_pass_desc.pResolveAttachments = NULL;
1478 sub_pass_desc.pDepthStencilAttachment = ds_reference;
1479 sub_pass_desc.preserveAttachmentCount = 0;
1480 sub_pass_desc.pPreserveAttachments = NULL;
1482 pass_desc.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO;
1483 pass_desc.pNext = NULL;
1484 pass_desc.flags = 0;
1485 pass_desc.attachmentCount = attachment_count;
1486 pass_desc.pAttachments = attachments;
1487 pass_desc.subpassCount = 1;
1488 pass_desc.pSubpasses = &sub_pass_desc;
1489 pass_desc.dependencyCount = 0;
1490 pass_desc.pDependencies = NULL;
1492 pass->key = *key;
1493 if ((vr = VK_CALL(vkCreateRenderPass(device_vk->vk_device,
1494 &pass_desc, NULL, &pass->vk_render_pass))) < 0)
1496 WARN("Failed to create Vulkan render pass, vr %d.\n", vr);
1497 return false;
1500 return true;
1503 VkRenderPass wined3d_context_vk_get_render_pass(struct wined3d_context_vk *context_vk,
1504 const struct wined3d_fb_state *fb, unsigned int rt_count, bool depth_stencil, uint32_t clear_flags)
1506 struct wined3d_render_pass_key_vk key;
1507 struct wined3d_render_pass_vk *pass;
1508 struct wine_rb_entry *entry;
1510 wined3d_render_pass_key_vk_init(&key, fb, rt_count, depth_stencil, clear_flags);
1511 if ((entry = wine_rb_get(&context_vk->render_passes, &key)))
1512 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_render_pass_vk, entry)->vk_render_pass;
1514 if (!(pass = heap_alloc(sizeof(*pass))))
1515 return VK_NULL_HANDLE;
1517 if (!wined3d_render_pass_vk_init(pass, context_vk, &key))
1519 heap_free(pass);
1520 return VK_NULL_HANDLE;
1523 if (wine_rb_put(&context_vk->render_passes, &pass->key, &pass->entry) == -1)
1525 ERR("Failed to insert render pass.\n");
1526 wined3d_render_pass_vk_cleanup(pass, context_vk);
1527 heap_free(pass);
1528 return VK_NULL_HANDLE;
1531 return pass->vk_render_pass;
1534 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk *context_vk)
1536 VkCommandBuffer vk_command_buffer = context_vk->current_command_buffer.vk_command_buffer;
1537 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1538 struct wined3d_query_vk *query_vk;
1540 if (context_vk->vk_render_pass)
1542 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1543 wined3d_query_vk_suspend(query_vk, context_vk);
1545 VK_CALL(vkCmdEndRenderPass(vk_command_buffer));
1546 context_vk->vk_render_pass = VK_NULL_HANDLE;
1547 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
1548 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0, 0, NULL, 0, NULL, 0, NULL));
1550 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
1552 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1554 ERR("Failed to allocate new query.\n");
1555 break;
1560 if (context_vk->vk_framebuffer)
1562 wined3d_context_vk_destroy_vk_framebuffer(context_vk,
1563 context_vk->vk_framebuffer, context_vk->current_command_buffer.id);
1564 context_vk->vk_framebuffer = VK_NULL_HANDLE;
1568 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry *entry, void *ctx)
1570 struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1571 struct wined3d_render_pass_vk, entry);
1573 wined3d_render_pass_vk_cleanup(pass, ctx);
1574 heap_free(pass);
1577 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk *writes)
1579 heap_free(writes->writes);
1582 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk *context_vk, struct list *free_pools)
1584 struct wined3d_query_pool_vk *pool_vk, *entry;
1586 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1588 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1589 heap_free(pool_vk);
1593 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk *context_vk,
1594 enum wined3d_query_type type, struct wined3d_query_pool_idx_vk *pool_idx)
1596 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1597 struct wined3d_query_pool_vk *pool_vk, *entry;
1598 struct wined3d_device_vk *device_vk;
1599 struct list *free_pools;
1600 VkResult vr;
1601 size_t idx;
1603 switch (type)
1605 case WINED3D_QUERY_TYPE_OCCLUSION:
1606 free_pools = &context_vk->free_occlusion_query_pools;
1607 break;
1609 case WINED3D_QUERY_TYPE_TIMESTAMP:
1610 free_pools = &context_vk->free_timestamp_query_pools;
1611 break;
1613 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS:
1614 free_pools = &context_vk->free_pipeline_statistics_query_pools;
1615 break;
1617 case WINED3D_QUERY_TYPE_SO_STATISTICS:
1618 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0:
1619 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1:
1620 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2:
1621 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3:
1622 free_pools = &context_vk->free_stream_output_statistics_query_pools;
1623 break;
1625 default:
1626 FIXME("Unhandled query type %#x.\n", type);
1627 return false;
1630 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, entry, free_pools, struct wined3d_query_pool_vk, entry)
1632 if (wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1633 goto done;
1634 list_remove(&pool_vk->entry);
1635 list_init(&pool_vk->entry);
1638 if (!(pool_vk = heap_alloc_zero(sizeof(*pool_vk))))
1639 return false;
1640 if (!wined3d_query_pool_vk_init(pool_vk, context_vk, type, free_pools))
1642 heap_free(pool_vk);
1643 return false;
1646 device_vk = wined3d_device_vk(context_vk->c.device);
1648 if (vk_info->supported[WINED3D_VK_EXT_HOST_QUERY_RESET])
1650 VK_CALL(vkResetQueryPoolEXT(device_vk->vk_device,
1651 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1653 else
1655 VkEventCreateInfo event_create_info;
1657 wined3d_context_vk_end_current_render_pass(context_vk);
1658 VK_CALL(vkCmdResetQueryPool(wined3d_context_vk_get_command_buffer(context_vk),
1659 pool_vk->vk_query_pool, 0, WINED3D_QUERY_POOL_SIZE));
1661 event_create_info.sType = VK_STRUCTURE_TYPE_EVENT_CREATE_INFO;
1662 event_create_info.pNext = NULL;
1663 event_create_info.flags = 0;
1665 /* We probably shouldn't call vkGetQueryPoolResults() without synchronizing with vkCmdResetQueryPool()
1666 * even if the query pool is freshly allocated. wined3d_query_vk_accumulate_data() will check this event
1667 * before returning results. */
1668 vr = VK_CALL(vkCreateEvent(device_vk->vk_device, &event_create_info, NULL, &pool_vk->vk_event));
1669 if (vr == VK_SUCCESS)
1671 /* At which stage vkCmdResetQueryPool() executes? */
1672 VK_CALL(vkCmdSetEvent(wined3d_context_vk_get_command_buffer(context_vk), pool_vk->vk_event,
1673 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT));
1675 else
1677 ERR("Failed to create event, vr %s.\n", wined3d_debug_vkresult(vr));
1681 if (!wined3d_query_pool_vk_allocate_query(pool_vk, &idx))
1683 wined3d_query_pool_vk_cleanup(pool_vk, context_vk);
1684 heap_free(pool_vk);
1685 return false;
1688 done:
1689 pool_idx->pool_vk = pool_vk;
1690 pool_idx->idx = idx;
1692 return true;
1695 void wined3d_context_vk_cleanup(struct wined3d_context_vk *context_vk)
1697 struct wined3d_command_buffer_vk *buffer = &context_vk->current_command_buffer;
1698 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1699 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1700 unsigned int i;
1702 if (buffer->vk_command_buffer)
1704 free_command_buffer(context_vk, buffer);
1705 buffer->vk_command_buffer = VK_NULL_HANDLE;
1708 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1709 context_vk->completed_command_buffer_id = buffer->id;
1710 for (i = 0; i < context_vk->completed.buffer_count; ++i)
1711 free_command_buffer(context_vk, &context_vk->completed.buffers[i]);
1713 heap_free(context_vk->compute.bindings.bindings);
1714 heap_free(context_vk->graphics.bindings.bindings);
1715 for (i = 0; i < context_vk->vk_descriptor_pool_count; ++i)
1716 VK_CALL(vkDestroyDescriptorPool(device_vk->vk_device, context_vk->vk_descriptor_pools[i], NULL));
1717 heap_free(context_vk->vk_descriptor_pools);
1718 if (context_vk->vk_framebuffer)
1719 VK_CALL(vkDestroyFramebuffer(device_vk->vk_device, context_vk->vk_framebuffer, NULL));
1720 if (context_vk->vk_so_counter_bo.vk_buffer)
1721 wined3d_context_vk_destroy_bo(context_vk, &context_vk->vk_so_counter_bo);
1722 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1723 /* Destroy the command pool after cleaning up resources. In particular,
1724 * this needs to happen after all command buffers are freed, because
1725 * vkFreeCommandBuffers() requires a valid pool handle. */
1726 VK_CALL(vkDestroyCommandPool(device_vk->vk_device, context_vk->vk_command_pool, NULL));
1727 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_occlusion_query_pools);
1728 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_timestamp_query_pools);
1729 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_pipeline_statistics_query_pools);
1730 wined3d_context_vk_destroy_query_pools(context_vk, &context_vk->free_stream_output_statistics_query_pools);
1731 wine_rb_destroy(&context_vk->bo_slab_available, wined3d_context_vk_destroy_bo_slab, context_vk);
1732 heap_free(context_vk->submitted.buffers);
1733 heap_free(context_vk->completed.buffers);
1734 heap_free(context_vk->retired.objects);
1736 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk->descriptor_writes);
1737 wine_rb_destroy(&context_vk->graphics_pipelines, wined3d_context_vk_destroy_graphics_pipeline, context_vk);
1738 wine_rb_destroy(&context_vk->pipeline_layouts, wined3d_context_vk_destroy_pipeline_layout, context_vk);
1739 wine_rb_destroy(&context_vk->render_passes, wined3d_context_vk_destroy_render_pass, context_vk);
1741 wined3d_context_cleanup(&context_vk->c);
1744 VkCommandBuffer wined3d_context_vk_get_command_buffer(struct wined3d_context_vk *context_vk)
1746 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1747 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1748 struct wined3d_command_buffer_vk *buffer;
1749 VkCommandBufferBeginInfo begin_info;
1750 struct wined3d_query_vk *query_vk;
1751 VkResult vr;
1753 TRACE("context_vk %p.\n", context_vk);
1755 buffer = &context_vk->current_command_buffer;
1756 if (buffer->vk_command_buffer)
1758 if (context_vk->retired_bo_size > WINED3D_RETIRED_BO_SIZE_THRESHOLD)
1759 wined3d_context_vk_submit_command_buffer(context_vk, 0, NULL, NULL, 0, NULL);
1760 else
1762 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1763 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1764 return buffer->vk_command_buffer;
1768 if (context_vk->completed.buffer_count)
1770 const struct wined3d_command_buffer_vk *old_buffer;
1772 old_buffer = &context_vk->completed.buffers[--context_vk->completed.buffer_count];
1773 buffer->vk_command_buffer = old_buffer->vk_command_buffer;
1774 buffer->vk_fence = old_buffer->vk_fence;
1776 else
1778 VkCommandBufferAllocateInfo command_buffer_info;
1779 VkFenceCreateInfo fence_desc;
1781 fence_desc.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO;
1782 fence_desc.pNext = NULL;
1783 fence_desc.flags = 0;
1784 if ((vr = VK_CALL(vkCreateFence(device_vk->vk_device, &fence_desc, NULL, &buffer->vk_fence))) < 0)
1786 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr));
1787 return VK_NULL_HANDLE;
1790 command_buffer_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO;
1791 command_buffer_info.pNext = NULL;
1792 command_buffer_info.commandPool = context_vk->vk_command_pool;
1793 command_buffer_info.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
1794 command_buffer_info.commandBufferCount = 1;
1795 if ((vr = VK_CALL(vkAllocateCommandBuffers(device_vk->vk_device,
1796 &command_buffer_info, &buffer->vk_command_buffer))) < 0)
1798 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1799 VK_CALL(vkDestroyFence(device_vk->vk_device, buffer->vk_fence, NULL));
1800 return VK_NULL_HANDLE;
1804 begin_info.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
1805 begin_info.pNext = NULL;
1806 begin_info.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
1807 begin_info.pInheritanceInfo = NULL;
1808 if ((vr = VK_CALL(vkBeginCommandBuffer(buffer->vk_command_buffer, &begin_info))) < 0)
1810 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr));
1811 VK_CALL(vkFreeCommandBuffers(device_vk->vk_device, context_vk->vk_command_pool,
1812 1, &buffer->vk_command_buffer));
1813 return buffer->vk_command_buffer = VK_NULL_HANDLE;
1816 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1818 if (!wined3d_context_vk_allocate_query(context_vk, query_vk->q.type, &query_vk->pool_idx))
1820 ERR("Failed to allocate new query.\n");
1821 break;
1824 wined3d_query_vk_resume(query_vk, context_vk);
1827 TRACE("Created new command buffer %p with id 0x%s.\n",
1828 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1830 return buffer->vk_command_buffer;
1833 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk *context_vk,
1834 unsigned int wait_semaphore_count, const VkSemaphore *wait_semaphores, const VkPipelineStageFlags *wait_stages,
1835 unsigned int signal_semaphore_count, const VkSemaphore *signal_semaphores)
1837 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1838 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1839 struct wined3d_query_pool_vk *pool_vk, *pool_vk_next;
1840 struct wined3d_command_buffer_vk *buffer;
1841 struct wined3d_query_vk *query_vk;
1842 VkSubmitInfo submit_info;
1843 VkResult vr;
1845 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1846 "signal_semaphore_count %u, signal_semaphores %p.\n",
1847 context_vk, wait_semaphore_count, wait_semaphores, wait_stages,
1848 signal_semaphore_count, signal_semaphores);
1850 buffer = &context_vk->current_command_buffer;
1851 if (!buffer->vk_command_buffer)
1852 return;
1854 TRACE("Submitting command buffer %p with id 0x%s.\n",
1855 buffer->vk_command_buffer, wine_dbgstr_longlong(buffer->id));
1857 wined3d_context_vk_end_current_render_pass(context_vk);
1859 LIST_FOR_EACH_ENTRY_SAFE(pool_vk, pool_vk_next, &context_vk->completed_query_pools,
1860 struct wined3d_query_pool_vk, completed_entry)
1862 list_remove(&pool_vk->completed_entry);
1863 list_init(&pool_vk->completed_entry);
1865 wined3d_context_vk_reset_completed_queries(context_vk, pool_vk, buffer);
1868 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->active_queries, struct wined3d_query_vk, entry)
1869 wined3d_query_vk_suspend(query_vk, context_vk);
1871 context_vk->graphics.vk_pipeline = VK_NULL_HANDLE;
1872 context_vk->update_compute_pipeline = 1;
1873 context_vk->update_stream_output = 1;
1874 context_vk->c.update_shader_resource_bindings = 1;
1875 context_vk->c.update_compute_shader_resource_bindings = 1;
1876 context_vk->c.update_unordered_access_view_bindings = 1;
1877 context_vk->c.update_compute_unordered_access_view_bindings = 1;
1878 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
1879 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
1880 context_invalidate_state(&context_vk->c, STATE_BLEND_FACTOR);
1881 context_invalidate_state(&context_vk->c, STATE_STENCIL_REF);
1883 VK_CALL(vkEndCommandBuffer(buffer->vk_command_buffer));
1885 VK_CALL(vkResetFences(device_vk->vk_device, 1, &buffer->vk_fence));
1887 submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
1888 submit_info.pNext = NULL;
1889 submit_info.waitSemaphoreCount = wait_semaphore_count;
1890 submit_info.pWaitSemaphores = wait_semaphores;
1891 submit_info.pWaitDstStageMask = wait_stages;
1892 submit_info.commandBufferCount = 1;
1893 submit_info.pCommandBuffers = &buffer->vk_command_buffer;
1894 submit_info.signalSemaphoreCount = signal_semaphore_count;
1895 submit_info.pSignalSemaphores = signal_semaphores;
1897 if ((vr = VK_CALL(vkQueueSubmit(device_vk->vk_queue, 1, &submit_info, buffer->vk_fence))) < 0)
1898 ERR("Failed to submit command buffer %p, vr %s.\n",
1899 buffer->vk_command_buffer, wined3d_debug_vkresult(vr));
1901 if (!wined3d_array_reserve((void **)&context_vk->submitted.buffers, &context_vk->submitted.buffers_size,
1902 context_vk->submitted.buffer_count + 1, sizeof(*context_vk->submitted.buffers)))
1903 ERR("Failed to grow submitted command buffer array.\n");
1905 context_vk->submitted.buffers[context_vk->submitted.buffer_count++] = *buffer;
1907 buffer->vk_command_buffer = VK_NULL_HANDLE;
1908 /* We don't expect this to ever happen, but handle it anyway. */
1909 if (!++buffer->id)
1911 wined3d_context_vk_wait_command_buffer(context_vk, buffer->id - 1);
1912 context_vk->completed_command_buffer_id = 0;
1913 buffer->id = 1;
1915 context_vk->retired_bo_size = 0;
1916 wined3d_context_vk_cleanup_resources(context_vk, VK_NULL_HANDLE);
1919 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk *context_vk, uint64_t id)
1921 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
1922 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1923 VkFence vk_fence;
1924 SIZE_T i;
1926 if (id <= context_vk->completed_command_buffer_id
1927 || id > context_vk->current_command_buffer.id) /* In case the buffer ID wrapped. */
1928 return;
1930 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1932 if (context_vk->submitted.buffers[i].id != id)
1933 continue;
1935 vk_fence = context_vk->submitted.buffers[i].vk_fence;
1936 wined3d_context_vk_cleanup_resources(context_vk, vk_fence);
1937 for (i = 0; i < context_vk->submitted.buffer_count; ++i)
1939 if (context_vk->submitted.buffers[i].id != id)
1940 continue;
1942 VK_CALL(vkWaitForFences(device_vk->vk_device, 1, &vk_fence, VK_TRUE, UINT64_MAX));
1943 wined3d_context_vk_remove_command_buffer(context_vk, i);
1944 return;
1948 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id));
1951 void wined3d_context_vk_image_barrier(struct wined3d_context_vk *context_vk,
1952 VkCommandBuffer vk_command_buffer, VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask,
1953 VkAccessFlags src_access_mask, VkAccessFlags dst_access_mask, VkImageLayout old_layout,
1954 VkImageLayout new_layout, VkImage image, const VkImageSubresourceRange *range)
1956 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
1957 VkImageMemoryBarrier barrier;
1959 wined3d_context_vk_end_current_render_pass(context_vk);
1961 barrier.sType = VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER;
1962 barrier.pNext = NULL;
1963 barrier.srcAccessMask = src_access_mask;
1964 barrier.dstAccessMask = dst_access_mask;
1965 barrier.oldLayout = old_layout;
1966 barrier.newLayout = new_layout;
1967 barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1968 barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
1969 barrier.image = image;
1970 barrier.subresourceRange = *range;
1972 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer, src_stage_mask, dst_stage_mask, 0, 0, NULL, 0, NULL, 1, &barrier));
1975 static int wined3d_render_pass_vk_compare(const void *key, const struct wine_rb_entry *entry)
1977 const struct wined3d_render_pass_key_vk *k = key;
1978 const struct wined3d_render_pass_vk *pass = WINE_RB_ENTRY_VALUE(entry,
1979 const struct wined3d_render_pass_vk, entry);
1981 return memcmp(k, &pass->key, sizeof(*k));
1984 static int wined3d_pipeline_layout_vk_compare(const void *key, const struct wine_rb_entry *entry)
1986 const struct wined3d_pipeline_layout_key_vk *a = key;
1987 const struct wined3d_pipeline_layout_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
1988 const struct wined3d_pipeline_layout_vk, entry)->key;
1989 int ret;
1991 if ((ret = wined3d_uint32_compare(a->binding_count, b->binding_count)))
1992 return ret;
1993 return memcmp(a->bindings, b->bindings, a->binding_count * sizeof(*a->bindings));
1996 static int wined3d_graphics_pipeline_vk_compare(const void *key, const struct wine_rb_entry *entry)
1998 const struct wined3d_graphics_pipeline_key_vk *a = key;
1999 const struct wined3d_graphics_pipeline_key_vk *b = &WINE_RB_ENTRY_VALUE(entry,
2000 const struct wined3d_graphics_pipeline_vk, entry)->key;
2001 unsigned int i;
2002 int ret;
2004 if ((ret = wined3d_uint32_compare(a->pipeline_desc.stageCount, b->pipeline_desc.stageCount)))
2005 return ret;
2006 for (i = 0; i < a->pipeline_desc.stageCount; ++i)
2008 if ((ret = wined3d_uint64_compare(a->stages[i].module, b->stages[i].module)))
2009 return ret;
2012 if ((ret = wined3d_uint32_compare(a->divisor_desc.vertexBindingDivisorCount,
2013 b->divisor_desc.vertexBindingDivisorCount)))
2014 return ret;
2015 if ((ret = memcmp(a->divisors, b->divisors,
2016 a->divisor_desc.vertexBindingDivisorCount * sizeof(*a->divisors))))
2017 return ret;
2019 if ((ret = wined3d_uint32_compare(a->input_desc.vertexAttributeDescriptionCount,
2020 b->input_desc.vertexAttributeDescriptionCount)))
2021 return ret;
2022 if ((ret = memcmp(a->attributes, b->attributes,
2023 a->input_desc.vertexAttributeDescriptionCount * sizeof(*a->attributes))))
2024 return ret;
2025 if ((ret = wined3d_uint32_compare(a->input_desc.vertexBindingDescriptionCount,
2026 b->input_desc.vertexBindingDescriptionCount)))
2027 return ret;
2028 if ((ret = memcmp(a->bindings, b->bindings,
2029 a->input_desc.vertexBindingDescriptionCount * sizeof(*a->bindings))))
2030 return ret;
2032 if ((ret = wined3d_uint32_compare(a->ia_desc.topology, b->ia_desc.topology)))
2033 return ret;
2034 if ((ret = wined3d_uint32_compare(a->ia_desc.primitiveRestartEnable, b->ia_desc.primitiveRestartEnable)))
2035 return ret;
2037 if ((ret = wined3d_uint32_compare(a->ts_desc.patchControlPoints, b->ts_desc.patchControlPoints)))
2038 return ret;
2040 if ((ret = memcmp(a->viewports, b->viewports, sizeof(a->viewports))))
2041 return ret;
2042 if ((ret = memcmp(a->scissors, b->scissors, sizeof(a->scissors))))
2043 return ret;
2045 if ((ret = memcmp(&a->rs_desc, &b->rs_desc, sizeof(a->rs_desc))))
2046 return ret;
2048 if ((ret = wined3d_uint32_compare(a->ms_desc.rasterizationSamples, b->ms_desc.rasterizationSamples)))
2049 return ret;
2050 if ((ret = wined3d_uint32_compare(a->ms_desc.alphaToCoverageEnable, b->ms_desc.alphaToCoverageEnable)))
2051 return ret;
2052 if ((ret = wined3d_uint32_compare(a->sample_mask, b->sample_mask)))
2053 return ret;
2055 if ((ret = memcmp(&a->ds_desc, &b->ds_desc, sizeof(a->ds_desc))))
2056 return ret;
2058 if ((ret = wined3d_uint32_compare(a->blend_desc.attachmentCount, b->blend_desc.attachmentCount)))
2059 return ret;
2060 if ((ret = memcmp(a->blend_attachments, b->blend_attachments,
2061 a->blend_desc.attachmentCount * sizeof(*a->blend_attachments))))
2062 return ret;
2064 if ((ret = wined3d_uint64_compare(a->pipeline_desc.layout, b->pipeline_desc.layout)))
2065 return ret;
2067 if ((ret = wined3d_uint64_compare(a->pipeline_desc.renderPass, b->pipeline_desc.renderPass)))
2068 return ret;
2070 return 0;
2073 static int wined3d_bo_slab_vk_compare(const void *key, const struct wine_rb_entry *entry)
2075 const struct wined3d_bo_slab_vk *slab = WINE_RB_ENTRY_VALUE(entry, const struct wined3d_bo_slab_vk, entry);
2076 const struct wined3d_bo_slab_vk_key *k = key;
2077 int ret;
2079 if ((ret = wined3d_uint32_compare(k->memory_type, slab->requested_memory_type)))
2080 return ret;
2081 if ((ret = wined3d_uint32_compare(k->usage, slab->bo.usage)))
2082 return ret;
2083 return wined3d_uint64_compare(k->size, slab->bo.size);
2086 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk *context_vk)
2088 struct wined3d_graphics_pipeline_key_vk *key;
2089 VkPipelineShaderStageCreateInfo *stage;
2090 unsigned int i;
2092 static const VkDynamicState dynamic_states[] =
2094 VK_DYNAMIC_STATE_BLEND_CONSTANTS,
2095 VK_DYNAMIC_STATE_STENCIL_REFERENCE,
2098 key = &context_vk->graphics.pipeline_key_vk;
2099 memset(key, 0, sizeof(*key));
2101 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2103 stage = &key->stages[i];
2104 stage->sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO;
2105 stage->pName = "main";
2108 key->input_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
2109 key->input_desc.pVertexBindingDescriptions = key->bindings;
2110 key->input_desc.pVertexAttributeDescriptions = key->attributes;
2112 key->divisor_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT;
2113 key->divisor_desc.pVertexBindingDivisors = key->divisors;
2115 key->ia_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO;
2117 key->ts_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO;
2119 key->vp_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO;
2120 key->vp_desc.pViewports = key->viewports;
2121 key->vp_desc.pScissors = key->scissors;
2123 key->rs_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
2124 key->rs_desc.lineWidth = 1.0f;
2126 key->ms_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO;
2127 key->ms_desc.pSampleMask = &key->sample_mask;
2129 key->ds_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO;
2130 key->ds_desc.maxDepthBounds = 1.0f;
2132 key->blend_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO;
2133 key->blend_desc.logicOp = VK_LOGIC_OP_COPY;
2134 key->blend_desc.pAttachments = key->blend_attachments;
2135 key->blend_desc.blendConstants[0] = 1.0f;
2136 key->blend_desc.blendConstants[1] = 1.0f;
2137 key->blend_desc.blendConstants[2] = 1.0f;
2138 key->blend_desc.blendConstants[3] = 1.0f;
2140 key->dynamic_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO;
2141 key->dynamic_desc.dynamicStateCount = ARRAY_SIZE(dynamic_states);
2142 key->dynamic_desc.pDynamicStates = dynamic_states;
2144 key->pipeline_desc.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO;
2145 key->pipeline_desc.pStages = key->stages;
2146 key->pipeline_desc.pVertexInputState = &key->input_desc;
2147 key->pipeline_desc.pInputAssemblyState = &key->ia_desc;
2148 key->pipeline_desc.pTessellationState = &key->ts_desc;
2149 key->pipeline_desc.pViewportState = &key->vp_desc;
2150 key->pipeline_desc.pRasterizationState = &key->rs_desc;
2151 key->pipeline_desc.pMultisampleState = &key->ms_desc;
2152 key->pipeline_desc.pDepthStencilState = &key->ds_desc;
2153 key->pipeline_desc.pColorBlendState = &key->blend_desc;
2154 key->pipeline_desc.pDynamicState = &key->dynamic_desc;
2155 key->pipeline_desc.basePipelineIndex = -1;
2158 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk *context_vk,
2159 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2161 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2162 VkPipelineRasterizationStateCreateInfo *desc = &key->rs_desc;
2163 const struct wined3d_rasterizer_state_desc *r;
2164 float scale_bias;
2165 union
2167 uint32_t u32;
2168 float f32;
2169 } const_bias;
2171 if (!state->rasterizer_state)
2173 desc->depthClampEnable = VK_FALSE;
2174 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2175 desc->cullMode = VK_CULL_MODE_BACK_BIT;
2176 desc->frontFace = VK_FRONT_FACE_CLOCKWISE;
2177 desc->depthBiasEnable = VK_FALSE;
2178 desc->depthBiasConstantFactor = 0.0f;
2179 desc->depthBiasClamp = 0.0f;
2180 desc->depthBiasSlopeFactor = 0.0f;
2182 return;
2185 r = &state->rasterizer_state->desc;
2186 desc->depthClampEnable = !r->depth_clip;
2187 desc->rasterizerDiscardEnable = is_rasterization_disabled(state->shader[WINED3D_SHADER_TYPE_GEOMETRY]);
2188 desc->cullMode = vk_cull_mode_from_wined3d(r->cull_mode);
2189 desc->frontFace = r->front_ccw ? VK_FRONT_FACE_COUNTER_CLOCKWISE : VK_FRONT_FACE_CLOCKWISE;
2191 scale_bias = r->scale_bias;
2192 const_bias.f32 = r->depth_bias;
2193 if (!scale_bias && !const_bias.f32)
2195 desc->depthBiasEnable = VK_FALSE;
2196 desc->depthBiasConstantFactor = 0.0f;
2197 desc->depthBiasClamp = 0.0f;
2198 desc->depthBiasSlopeFactor = 0.0f;
2200 return;
2203 desc->depthBiasEnable = VK_TRUE;
2204 if (d3d_info->wined3d_creation_flags & WINED3D_LEGACY_DEPTH_BIAS)
2206 const struct wined3d_rendertarget_view *dsv;
2208 if ((dsv = state->fb.depth_stencil))
2210 desc->depthBiasConstantFactor = -(float)const_bias.u32 / dsv->format->depth_bias_scale;
2211 desc->depthBiasSlopeFactor = -(float)const_bias.u32;
2213 else
2215 desc->depthBiasConstantFactor = 0.0f;
2216 desc->depthBiasSlopeFactor = 0.0f;
2219 else
2221 desc->depthBiasConstantFactor = const_bias.f32;
2222 desc->depthBiasSlopeFactor = scale_bias;
2224 desc->depthBiasClamp = r->depth_bias_clamp;
2227 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk *context_vk,
2228 const struct wined3d_state *state, struct wined3d_graphics_pipeline_key_vk *key)
2230 VkPipelineColorBlendStateCreateInfo *desc = &key->blend_desc;
2231 const struct wined3d_blend_state_desc *b;
2232 unsigned int i;
2234 desc->attachmentCount = context_vk->rt_count;
2236 memset(key->blend_attachments, 0, sizeof(key->blend_attachments));
2237 if (!state->blend_state)
2239 for (i = 0; i < context_vk->rt_count; ++i)
2241 key->blend_attachments[i].colorWriteMask = VK_COLOR_COMPONENT_R_BIT
2242 | VK_COLOR_COMPONENT_G_BIT
2243 | VK_COLOR_COMPONENT_B_BIT
2244 | VK_COLOR_COMPONENT_A_BIT;
2247 return;
2250 b = &state->blend_state->desc;
2251 for (i = 0; i < context_vk->rt_count; ++i)
2253 const struct wined3d_rendertarget_blend_state_desc *rt = &b->rt[b->independent ? i : 0];
2254 const struct wined3d_rendertarget_view *rtv = state->fb.render_targets[i];
2255 VkPipelineColorBlendAttachmentState *a = &key->blend_attachments[i];
2256 enum wined3d_blend src_blend, dst_blend;
2257 const struct wined3d_format *rt_format;
2259 a->colorWriteMask = vk_colour_write_mask_from_wined3d(rt->writemask);
2260 if (!rt->enable)
2261 continue;
2263 if (rtv)
2264 rt_format = rtv->format;
2265 else
2266 rt_format = wined3d_get_format(context_vk->c.device->adapter, WINED3DFMT_NULL, 0);
2267 a->blendEnable = VK_TRUE;
2269 src_blend = rt->src;
2270 dst_blend = rt->dst;
2271 if (src_blend == WINED3D_BLEND_BOTHSRCALPHA)
2273 src_blend = WINED3D_BLEND_SRCALPHA;
2274 dst_blend = WINED3D_BLEND_INVSRCALPHA;
2276 else if (src_blend == WINED3D_BLEND_BOTHINVSRCALPHA)
2278 src_blend = WINED3D_BLEND_INVSRCALPHA;
2279 dst_blend = WINED3D_BLEND_SRCALPHA;
2281 a->srcColorBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, FALSE);
2282 a->dstColorBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, FALSE);
2283 a->colorBlendOp = vk_blend_op_from_wined3d(rt->op);
2285 src_blend = rt->src_alpha;
2286 dst_blend = rt->dst_alpha;
2287 a->srcAlphaBlendFactor = vk_blend_factor_from_wined3d(src_blend, rt_format, TRUE);
2288 a->dstAlphaBlendFactor = vk_blend_factor_from_wined3d(dst_blend, rt_format, TRUE);
2289 a->alphaBlendOp = vk_blend_op_from_wined3d(rt->op_alpha);
2293 static VkFormat vk_format_from_component_type(enum wined3d_component_type component_type)
2295 switch (component_type)
2297 case WINED3D_TYPE_UINT:
2298 return VK_FORMAT_R32G32B32A32_UINT;
2299 case WINED3D_TYPE_INT:
2300 return VK_FORMAT_R32G32B32A32_SINT;
2301 case WINED3D_TYPE_UNKNOWN:
2302 case WINED3D_TYPE_FLOAT:
2303 return VK_FORMAT_R32G32B32A32_SFLOAT;
2305 return VK_FORMAT_UNDEFINED;
2308 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk *context_vk,
2309 const struct wined3d_state *state, VkPipelineLayout vk_pipeline_layout, uint32_t *null_buffer_binding)
2311 unsigned int i, attribute_count, binding_count, divisor_count, stage_count;
2312 const struct wined3d_d3d_info *d3d_info = context_vk->c.d3d_info;
2313 struct wined3d_graphics_pipeline_key_vk *key;
2314 VkPipelineShaderStageCreateInfo *stage;
2315 struct wined3d_stream_info stream_info;
2316 struct wined3d_shader *vertex_shader;
2317 VkPrimitiveTopology vk_topology;
2318 VkShaderModule module;
2319 bool update = false;
2320 uint32_t mask;
2322 *null_buffer_binding = ~0u;
2323 key = &context_vk->graphics.pipeline_key_vk;
2325 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
2327 stage_count = 0;
2328 for (i = 0; i < ARRAY_SIZE(context_vk->graphics.vk_modules); ++i)
2330 if (!(module = context_vk->graphics.vk_modules[i]))
2331 continue;
2333 stage = &key->stages[stage_count++];
2334 stage->stage = vk_shader_stage_from_wined3d(i);
2335 stage->module = module;
2338 key->pipeline_desc.stageCount = stage_count;
2340 update = true;
2343 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VDECL)
2344 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC)
2345 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
2347 VkVertexInputAttributeDescription *a;
2348 VkVertexInputBindingDescription *b;
2350 wined3d_stream_info_from_declaration(&stream_info, state, d3d_info);
2351 divisor_count = 0;
2352 for (i = 0, mask = 0, attribute_count = 0, binding_count = 0; i < ARRAY_SIZE(stream_info.elements); ++i)
2354 VkVertexInputBindingDivisorDescriptionEXT *d;
2355 struct wined3d_stream_info_element *e;
2356 uint32_t binding;
2358 if (!(stream_info.use_map & (1u << i)))
2359 continue;
2361 a = &key->attributes[attribute_count++];
2362 e = &stream_info.elements[i];
2363 binding = e->stream_idx;
2365 a->location = i;
2366 a->binding = binding;
2367 a->format = wined3d_format_vk(e->format)->vk_format;
2368 a->offset = (UINT_PTR)e->data.addr - state->streams[binding].offset;
2370 if (mask & (1u << binding))
2371 continue;
2372 mask |= 1u << binding;
2374 b = &key->bindings[binding_count++];
2375 b->binding = binding;
2376 b->stride = e->stride;
2377 b->inputRate = e->instanced ? VK_VERTEX_INPUT_RATE_INSTANCE : VK_VERTEX_INPUT_RATE_VERTEX;
2379 if (e->instanced)
2381 d = &key->divisors[divisor_count++];
2382 d->binding = binding;
2383 d->divisor = e->divisor;
2387 vertex_shader = state->shader[WINED3D_SHADER_TYPE_VERTEX];
2388 if (vertex_shader && (mask = ~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2390 struct wined3d_shader_signature_element *element;
2391 struct wined3d_shader_signature *signature;
2392 uint32_t null_binding, location;
2394 if (!wined3d_get_unused_stream_index(state, &null_binding))
2396 ERR("No streams left for a null buffer binding.\n");
2398 else
2400 signature = &vertex_shader->input_signature;
2401 for (i = 0; i < signature->element_count; ++i)
2403 element = &signature->elements[i];
2404 location = element->register_idx;
2406 if (!(mask & (1u << location)) || element->sysval_semantic)
2407 continue;
2408 mask &= ~(1u << location);
2410 a = &key->attributes[attribute_count++];
2411 a->location = location;
2412 a->binding = null_binding;
2413 a->format = vk_format_from_component_type(element->component_type);
2414 a->offset = 0;
2417 if (mask != (~stream_info.use_map & vertex_shader->reg_maps.input_registers))
2419 b = &key->bindings[binding_count++];
2420 *null_buffer_binding = b->binding = null_binding;
2421 b->stride = 0;
2422 b->inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
2427 key->input_desc.pNext = NULL;
2428 key->input_desc.vertexBindingDescriptionCount = binding_count;
2429 key->input_desc.vertexAttributeDescriptionCount = attribute_count;
2431 if (divisor_count)
2433 key->input_desc.pNext = &key->divisor_desc;
2434 key->divisor_desc.vertexBindingDivisorCount = divisor_count;
2437 update = true;
2440 vk_topology = vk_topology_from_wined3d(state->primitive_type);
2441 if (key->ia_desc.topology != vk_topology)
2443 key->ia_desc.topology = vk_topology;
2444 key->ia_desc.primitiveRestartEnable = !(d3d_info->wined3d_creation_flags & WINED3D_NO_PRIMITIVE_RESTART)
2445 && !wined3d_primitive_type_is_list(state->primitive_type);
2447 update = true;
2450 if (key->ts_desc.patchControlPoints != state->patch_vertex_count)
2452 key->ts_desc.patchControlPoints = state->patch_vertex_count;
2454 update = true;
2457 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_VIEWPORT)
2458 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SCISSORRECT)
2459 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER))
2461 key->vp_desc.viewportCount = (context_vk->vk_info->multiple_viewports ? WINED3D_MAX_VIEWPORTS : 1);
2462 key->vp_desc.scissorCount = key->vp_desc.viewportCount;
2464 for (i = 0; i < key->vp_desc.viewportCount; ++i)
2466 const struct wined3d_viewport *src_viewport = &state->viewports[i];
2467 VkViewport *viewport = &key->viewports[i];
2468 VkRect2D *scissor = &key->scissors[i];
2470 if (i >= state->viewport_count)
2472 viewport->x = 0.0f;
2473 viewport->y = 0.0f;
2474 viewport->width = 1.0f;
2475 viewport->height = 1.0f;
2476 viewport->minDepth = 0.0f;
2477 viewport->maxDepth = 0.0f;
2479 memset(scissor, 0, sizeof(*scissor));
2480 continue;
2483 viewport->x = src_viewport->x;
2484 viewport->y = src_viewport->y;
2485 viewport->width = src_viewport->width;
2486 viewport->height = src_viewport->height;
2487 viewport->minDepth = src_viewport->min_z;
2488 viewport->maxDepth = src_viewport->max_z;
2490 if (state->rasterizer_state && state->rasterizer_state->desc.scissor)
2492 const RECT *r = &state->scissor_rects[i];
2494 if (i >= state->scissor_rect_count)
2496 memset(scissor, 0, sizeof(*scissor));
2497 continue;
2500 scissor->offset.x = r->left;
2501 scissor->offset.y = r->top;
2502 scissor->extent.width = r->right - r->left;
2503 scissor->extent.height = r->bottom - r->top;
2505 else
2507 scissor->offset.x = viewport->x;
2508 scissor->offset.y = viewport->y;
2509 scissor->extent.width = viewport->width;
2510 scissor->extent.height = viewport->height;
2512 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2513 if (scissor->offset.x < 0)
2514 scissor->offset.x = 0;
2515 if (scissor->offset.y < 0)
2516 scissor->offset.y = 0;
2517 viewport->y += viewport->height;
2518 viewport->height = -viewport->height;
2521 update = true;
2524 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_RASTERIZER)
2525 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
2527 wined3d_context_vk_update_rasterisation_state(context_vk, state, key);
2529 update = true;
2532 if (key->ms_desc.rasterizationSamples != context_vk->sample_count
2533 || isStateDirty(&context_vk->c, STATE_BLEND) || isStateDirty(&context_vk->c, STATE_SAMPLE_MASK))
2535 key->ms_desc.rasterizationSamples = context_vk->sample_count;
2536 key->ms_desc.alphaToCoverageEnable = state->blend_state && state->blend_state->desc.alpha_to_coverage;
2537 key->sample_mask = state->sample_mask;
2539 update = true;
2542 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_DEPTH_STENCIL)
2543 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2545 const struct wined3d_depth_stencil_state *d = state->depth_stencil_state;
2547 if (d)
2549 key->ds_desc.depthTestEnable = d->desc.depth;
2550 key->ds_desc.depthWriteEnable = d->desc.depth_write;
2551 key->ds_desc.depthCompareOp = vk_compare_op_from_wined3d(d->desc.depth_func);
2552 key->ds_desc.stencilTestEnable = state->fb.depth_stencil && d->desc.stencil;
2553 if (key->ds_desc.stencilTestEnable)
2555 key->ds_desc.front.failOp = vk_stencil_op_from_wined3d(d->desc.front.fail_op);
2556 key->ds_desc.front.passOp = vk_stencil_op_from_wined3d(d->desc.front.pass_op);
2557 key->ds_desc.front.depthFailOp = vk_stencil_op_from_wined3d(d->desc.front.depth_fail_op);
2558 key->ds_desc.front.compareOp = vk_compare_op_from_wined3d(d->desc.front.func);
2559 key->ds_desc.front.compareMask = d->desc.stencil_read_mask;
2560 key->ds_desc.front.writeMask = d->desc.stencil_write_mask;
2562 key->ds_desc.back.failOp = vk_stencil_op_from_wined3d(d->desc.back.fail_op);
2563 key->ds_desc.back.passOp = vk_stencil_op_from_wined3d(d->desc.back.pass_op);
2564 key->ds_desc.back.depthFailOp = vk_stencil_op_from_wined3d(d->desc.back.depth_fail_op);
2565 key->ds_desc.back.compareOp = vk_compare_op_from_wined3d(d->desc.back.func);
2566 key->ds_desc.back.compareMask = d->desc.stencil_read_mask;
2567 key->ds_desc.back.writeMask = d->desc.stencil_write_mask;
2569 else
2571 memset(&key->ds_desc.front, 0, sizeof(key->ds_desc.front));
2572 memset(&key->ds_desc.back, 0, sizeof(key->ds_desc.back));
2575 else
2577 key->ds_desc.depthTestEnable = VK_TRUE;
2578 key->ds_desc.depthWriteEnable = VK_TRUE;
2579 key->ds_desc.depthCompareOp = VK_COMPARE_OP_LESS;
2580 key->ds_desc.stencilTestEnable = VK_FALSE;
2583 update = true;
2586 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND)
2587 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
2589 wined3d_context_vk_update_blend_state(context_vk, state, key);
2591 update = true;
2594 if (key->pipeline_desc.layout != vk_pipeline_layout)
2596 key->pipeline_desc.layout = vk_pipeline_layout;
2598 update = true;
2601 if (key->pipeline_desc.renderPass != context_vk->vk_render_pass)
2603 key->pipeline_desc.renderPass = context_vk->vk_render_pass;
2605 update = true;
2608 return update;
2611 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk *context_vk,
2612 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2614 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2615 VkClearValue clear_values[WINED3D_MAX_RENDER_TARGETS + 1];
2616 VkImageView vk_views[WINED3D_MAX_RENDER_TARGETS + 1];
2617 unsigned int fb_width, fb_height, fb_layer_count;
2618 struct wined3d_rendertarget_view_vk *rtv_vk;
2619 struct wined3d_rendertarget_view *view;
2620 const VkPhysicalDeviceLimits *limits;
2621 struct wined3d_query_vk *query_vk;
2622 VkRenderPassBeginInfo begin_info;
2623 unsigned int attachment_count, i;
2624 struct wined3d_texture *texture;
2625 VkFramebufferCreateInfo fb_desc;
2626 VkResult vr;
2628 if (context_vk->vk_render_pass)
2629 return true;
2631 limits = &wined3d_adapter_vk(device_vk->d.adapter)->device_limits;
2632 fb_width = limits->maxFramebufferWidth;
2633 fb_height = limits->maxFramebufferHeight;
2634 fb_layer_count = limits->maxFramebufferLayers;
2635 attachment_count = 0;
2637 context_vk->rt_count = 0;
2638 begin_info.clearValueCount = 0;
2639 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
2641 if (!(view = state->fb.render_targets[i]) || view->format->id == WINED3DFMT_NULL)
2642 continue;
2644 rtv_vk = wined3d_rendertarget_view_vk(view);
2646 if (rtv_vk->v.resource->bind_count)
2648 struct wined3d_texture_vk *texture_vk;
2649 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource));
2650 wined3d_texture_vk_make_generic(texture_vk, context_vk);
2653 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2654 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_RENDER_TARGET);
2655 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2657 if (view->width < fb_width)
2658 fb_width = view->width;
2659 if (view->height < fb_height)
2660 fb_height = view->height;
2661 if (view->layer_count < fb_layer_count)
2662 fb_layer_count = view->layer_count;
2663 context_vk->rt_count = i + 1;
2665 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2667 VkClearColorValue *c = &clear_values[attachment_count].color;
2669 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2671 c->int32[0] = c->int32[1] = c->int32[2] = c->int32[3] = 0;
2673 else
2675 texture = texture_from_resource(view->resource);
2676 wined3d_format_colour_to_vk(view->format,
2677 &texture->sub_resources[view->sub_resource_idx].clear_value.colour, c);
2680 begin_info.clearValueCount = attachment_count + 1;
2682 ++attachment_count;
2685 if ((view = state->fb.depth_stencil))
2687 rtv_vk = wined3d_rendertarget_view_vk(view);
2689 if (rtv_vk->v.resource->bind_count)
2691 struct wined3d_texture_vk *texture_vk;
2692 texture_vk = wined3d_texture_vk(wined3d_texture_from_resource(rtv_vk->v.resource));
2693 wined3d_texture_vk_make_generic(texture_vk, context_vk);
2696 vk_views[attachment_count] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk, context_vk);
2697 wined3d_rendertarget_view_vk_barrier(rtv_vk, context_vk, WINED3D_BIND_DEPTH_STENCIL);
2698 wined3d_context_vk_reference_rendertarget_view(context_vk, rtv_vk);
2700 if (view->width < fb_width)
2701 fb_width = view->width;
2702 if (view->height < fb_height)
2703 fb_height = view->height;
2704 if (view->layer_count < fb_layer_count)
2705 fb_layer_count = view->layer_count;
2707 if (wined3d_rendertarget_view_get_locations(view) & WINED3D_LOCATION_CLEARED)
2709 VkClearDepthStencilValue *c = &clear_values[attachment_count].depthStencil;
2711 if (view->resource->type == WINED3D_RTYPE_BUFFER)
2713 c->depth = 0.0f;
2714 c->stencil = 0;
2716 else
2718 texture = texture_from_resource(view->resource);
2719 c->depth = texture->sub_resources[view->sub_resource_idx].clear_value.depth;
2720 c->stencil = texture->sub_resources[view->sub_resource_idx].clear_value.stencil;
2722 begin_info.clearValueCount = attachment_count + 1;
2724 ++attachment_count;
2727 if (!(context_vk->vk_render_pass = wined3d_context_vk_get_render_pass(context_vk, &state->fb,
2728 ARRAY_SIZE(state->fb.render_targets), !!state->fb.depth_stencil, 0)))
2730 ERR("Failed to get render pass.\n");
2731 return false;
2734 fb_desc.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO;
2735 fb_desc.pNext = NULL;
2736 fb_desc.flags = 0;
2737 fb_desc.renderPass = context_vk->vk_render_pass;
2738 fb_desc.attachmentCount = attachment_count;
2739 fb_desc.pAttachments = vk_views;
2740 fb_desc.width = fb_width;
2741 fb_desc.height = fb_height;
2742 fb_desc.layers = fb_layer_count;
2744 if ((vr = VK_CALL(vkCreateFramebuffer(device_vk->vk_device, &fb_desc, NULL, &context_vk->vk_framebuffer))) < 0)
2746 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr));
2747 return false;
2750 begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
2751 begin_info.pNext = NULL;
2752 begin_info.renderPass = context_vk->vk_render_pass;
2753 begin_info.framebuffer = context_vk->vk_framebuffer;
2754 begin_info.renderArea.offset.x = 0;
2755 begin_info.renderArea.offset.y = 0;
2756 begin_info.renderArea.extent.width = fb_width;
2757 begin_info.renderArea.extent.height = fb_height;
2758 begin_info.pClearValues = clear_values;
2759 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer, &begin_info, VK_SUBPASS_CONTENTS_INLINE));
2761 LIST_FOR_EACH_ENTRY(query_vk, &context_vk->render_pass_queries, struct wined3d_query_vk, entry)
2762 wined3d_query_vk_resume(query_vk, context_vk);
2763 return true;
2766 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk *context_vk,
2767 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2769 VkDeviceSize offsets[ARRAY_SIZE(state->streams)] = {0};
2770 VkBuffer buffers[ARRAY_SIZE(state->streams)];
2771 const struct wined3d_stream_state *stream;
2772 const VkDescriptorBufferInfo *buffer_info;
2773 struct wined3d_buffer_vk *buffer_vk;
2774 struct wined3d_buffer *buffer;
2775 unsigned int i, first, count;
2777 first = 0;
2778 count = 0;
2779 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
2781 stream = &state->streams[i];
2783 if ((buffer = stream->buffer))
2785 buffer_vk = wined3d_buffer_vk(buffer);
2786 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2787 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2788 buffers[count] = buffer_info->buffer;
2789 offsets[count] = buffer_info->offset + stream->offset;
2790 ++count;
2791 continue;
2794 if (count)
2795 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2796 first = i + 1;
2797 count = 0;
2800 if (count)
2801 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, first, count, buffers, offsets));
2804 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk *context_vk,
2805 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, const struct wined3d_vk_info *vk_info)
2807 VkDeviceSize offsets[ARRAY_SIZE(state->stream_output)];
2808 VkDeviceSize sizes[ARRAY_SIZE(state->stream_output)];
2809 VkBuffer buffers[ARRAY_SIZE(state->stream_output)];
2810 const struct wined3d_stream_output *stream;
2811 const VkDescriptorBufferInfo *buffer_info;
2812 struct wined3d_buffer_vk *buffer_vk;
2813 struct wined3d_buffer *buffer;
2814 unsigned int i, first, count;
2816 if (!context_vk->vk_so_counter_bo.vk_buffer)
2818 struct wined3d_bo_vk *bo = &context_vk->vk_so_counter_bo;
2820 if (!wined3d_context_vk_create_bo(context_vk, ARRAY_SIZE(context_vk->vk_so_counters) * sizeof(uint32_t) * 2,
2821 VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT, bo))
2822 ERR("Failed to create counter BO.\n");
2824 for (i = 0; i < ARRAY_SIZE(context_vk->vk_so_counters); ++i)
2825 context_vk->vk_so_offsets[i] = bo->b.buffer_offset + i * sizeof(uint32_t) * 2;
2828 memset(context_vk->vk_so_counters, 0, sizeof(context_vk->vk_so_counters));
2829 first = 0;
2830 count = 0;
2831 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
2833 stream = &state->stream_output[i];
2835 if ((buffer = stream->buffer))
2837 context_vk->vk_so_counters[i] = context_vk->vk_so_counter_bo.vk_buffer;
2839 buffer_vk = wined3d_buffer_vk(buffer);
2840 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
2841 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
2842 buffers[count] = buffer_info->buffer;
2843 if ((offsets[count] = stream->offset) == ~0u)
2845 FIXME("Appending to stream output buffers not implemented.\n");
2846 offsets[count] = 0;
2848 sizes[count] = buffer_info->range - offsets[count];
2849 offsets[count] += buffer_info->offset;
2850 ++count;
2851 continue;
2854 if (count)
2855 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2856 first = i + 1;
2857 count = 0;
2860 if (count)
2861 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer, first, count, buffers, offsets, sizes));
2864 static VkResult wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk *device_vk,
2865 const struct wined3d_vk_info *vk_info, VkDescriptorPool *vk_pool)
2867 struct VkDescriptorPoolCreateInfo pool_desc;
2868 VkResult vr;
2870 static const VkDescriptorPoolSize pool_sizes[] =
2872 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1024},
2873 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, 1024},
2874 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, 1024},
2875 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, 1024},
2876 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1024},
2877 {VK_DESCRIPTOR_TYPE_SAMPLER, 1024},
2880 pool_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;
2881 pool_desc.pNext = NULL;
2882 pool_desc.flags = 0;
2883 pool_desc.maxSets = 512;
2884 pool_desc.poolSizeCount = ARRAY_SIZE(pool_sizes);
2885 pool_desc.pPoolSizes = pool_sizes;
2887 if ((vr = VK_CALL(vkCreateDescriptorPool(device_vk->vk_device, &pool_desc, NULL, vk_pool))) < 0)
2888 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2890 return vr;
2893 VkDescriptorPool wined3d_context_vk_get_vk_descriptor_pool(struct wined3d_context_vk *context_vk)
2895 VkResult vr;
2897 if (context_vk->vk_descriptor_pool_count)
2898 return context_vk->vk_descriptor_pools[0];
2900 if (!wined3d_array_reserve((void **)&context_vk->vk_descriptor_pools, &context_vk->vk_descriptor_pools_size,
2901 1, sizeof(*context_vk->vk_descriptor_pools)))
2903 ERR("Failed to allocate array.\n");
2904 return VK_NULL_HANDLE;
2907 if ((vr = wined3d_context_vk_create_vk_descriptor_pool(wined3d_device_vk(context_vk->c.device),
2908 context_vk->vk_info, context_vk->vk_descriptor_pools)))
2910 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr));
2911 return VK_NULL_HANDLE;
2914 context_vk->vk_descriptor_pool_count = 1;
2915 return context_vk->vk_descriptor_pools[0];
2918 VkDescriptorSet wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk *context_vk,
2919 VkDescriptorSetLayout vk_set_layout)
2921 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
2922 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
2923 struct VkDescriptorSetAllocateInfo set_desc;
2924 VkDescriptorPool vk_descriptor_pool;
2925 VkDescriptorSet vk_descriptor_set;
2926 VkResult vr;
2928 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2929 return VK_NULL_HANDLE;
2931 set_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO;
2932 set_desc.pNext = NULL;
2933 set_desc.descriptorPool = vk_descriptor_pool;
2934 set_desc.descriptorSetCount = 1;
2935 set_desc.pSetLayouts = &vk_set_layout;
2936 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2937 return vk_descriptor_set;
2939 if (vr == VK_ERROR_FRAGMENTED_POOL || vr == VK_ERROR_OUT_OF_POOL_MEMORY)
2941 wined3d_context_vk_reset_vk_descriptor_pool(context_vk,
2942 vk_descriptor_pool, context_vk->current_command_buffer.id);
2943 context_vk->vk_descriptor_pools[0] = context_vk->vk_descriptor_pools[--context_vk->vk_descriptor_pool_count];
2944 if (!(vk_descriptor_pool = wined3d_context_vk_get_vk_descriptor_pool(context_vk)))
2946 WARN("Failed to create descriptor pool.\n");
2947 return VK_NULL_HANDLE;
2950 set_desc.descriptorPool = vk_descriptor_pool;
2951 if ((vr = VK_CALL(vkAllocateDescriptorSets(device_vk->vk_device, &set_desc, &vk_descriptor_set))) >= 0)
2952 return vk_descriptor_set;
2955 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr));
2957 return VK_NULL_HANDLE;
2960 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk *writes,
2961 VkDescriptorSet vk_descriptor_set, size_t binding_idx, VkDescriptorType type,
2962 const VkDescriptorBufferInfo *buffer_info, const VkDescriptorImageInfo *image_info,
2963 const VkBufferView *buffer_view)
2965 SIZE_T write_count = writes->count;
2966 VkWriteDescriptorSet *write;
2968 if (!wined3d_array_reserve((void **)&writes->writes, &writes->size,
2969 write_count + 1, sizeof(*writes->writes)))
2970 return false;
2972 write = &writes->writes[write_count];
2973 write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
2974 write->pNext = NULL;
2975 write->dstSet = vk_descriptor_set;
2976 write->dstBinding = binding_idx;
2977 write->dstArrayElement = 0;
2978 write->descriptorCount = 1;
2979 write->descriptorType = type;
2980 write->pImageInfo = image_info;
2981 write->pBufferInfo = buffer_info;
2982 write->pTexelBufferView = buffer_view;
2984 ++writes->count;
2986 return true;
2989 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk *writes,
2990 VkDescriptorSet vk_descriptor_set, size_t binding_idx, enum wined3d_shader_resource_type type,
2991 enum wined3d_data_type data_type, struct wined3d_context_vk *context_vk)
2993 const struct wined3d_null_views_vk *v = &wined3d_device_vk(context_vk->c.device)->null_views_vk;
2995 switch (type)
2997 case WINED3D_SHADER_RESOURCE_BUFFER:
2998 if (data_type == WINED3D_DATA_FLOAT)
2999 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
3000 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_float);
3001 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding_idx,
3002 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, NULL, NULL, &v->vk_view_buffer_uint);
3004 case WINED3D_SHADER_RESOURCE_TEXTURE_1D:
3005 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3006 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d, NULL);
3008 case WINED3D_SHADER_RESOURCE_TEXTURE_2D:
3009 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3010 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d, NULL);
3012 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS:
3013 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3014 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms, NULL);
3016 case WINED3D_SHADER_RESOURCE_TEXTURE_3D:
3017 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3018 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_3d, NULL);
3020 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE:
3021 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3022 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube, NULL);
3024 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY:
3025 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3026 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_1d_array, NULL);
3028 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY:
3029 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3030 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2d_array, NULL);
3032 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY:
3033 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3034 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_2dms_array, NULL);
3036 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBEARRAY:
3037 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3038 binding_idx, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, NULL, &v->vk_info_cube_array, NULL);
3040 default:
3041 FIXME("Unhandled resource type %#x.\n", type);
3042 return false;
3046 static bool wined3d_shader_descriptor_writes_vk_add_cbv_write(struct wined3d_shader_descriptor_writes_vk *writes,
3047 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3048 const struct wined3d_shader_resource_binding *binding, VkDescriptorBufferInfo *buffer_info)
3050 const struct wined3d_constant_buffer_state *cb_state = &state->cb[binding->shader_type][binding->resource_idx];
3051 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3052 struct wined3d_buffer_vk *buffer_vk;
3053 struct wined3d_buffer *buffer;
3055 if (!(buffer = cb_state->buffer))
3056 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3057 VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, &device_vk->null_resources_vk.buffer_info, NULL, NULL);
3059 buffer_vk = wined3d_buffer_vk(buffer);
3060 *buffer_info = *wined3d_buffer_vk_get_buffer_info(buffer_vk);
3061 buffer_info->offset += cb_state->offset;
3062 buffer_info->range = min(cb_state->size, buffer_info->range);
3063 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3064 binding->binding_idx, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, buffer_info, NULL, NULL))
3065 return false;
3066 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer->buffer_object));
3067 return true;
3070 static bool wined3d_shader_descriptor_writes_vk_add_srv_write(struct wined3d_shader_descriptor_writes_vk *writes,
3071 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3072 const struct wined3d_shader_resource_binding *binding)
3074 struct wined3d_shader_resource_view_vk *srv_vk;
3075 struct wined3d_shader_resource_view *srv;
3076 const VkDescriptorImageInfo *image_info;
3077 struct wined3d_resource *resource;
3078 struct wined3d_view_vk *view_vk;
3079 VkBufferView *buffer_view;
3080 VkDescriptorType type;
3082 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3083 return wined3d_shader_resource_bindings_add_null_srv_binding(writes, vk_descriptor_set,
3084 binding->binding_idx, binding->resource_type, binding->resource_data_type, context_vk);
3086 resource = srv->resource;
3087 srv_vk = wined3d_shader_resource_view_vk(srv);
3088 view_vk = &srv_vk->view_vk;
3089 if (resource->type == WINED3D_RTYPE_BUFFER)
3091 image_info = NULL;
3092 buffer_view = &view_vk->u.vk_buffer_view;
3093 type = VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
3095 else
3097 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3099 if (view_vk->u.vk_image_info.imageView)
3101 image_info = &view_vk->u.vk_image_info;
3102 if (image_info->imageLayout != texture_vk->layout)
3103 wined3d_shader_resource_view_vk_update_layout(srv_vk, texture_vk->layout);
3105 else
3106 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3107 buffer_view = NULL;
3108 type = VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE;
3111 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3112 binding->binding_idx, type, NULL, image_info, buffer_view))
3113 return false;
3114 wined3d_context_vk_reference_shader_resource_view(context_vk, srv_vk);
3115 return true;
3118 static bool wined3d_shader_descriptor_writes_vk_add_uav_write(struct wined3d_shader_descriptor_writes_vk *writes,
3119 struct wined3d_context_vk *context_vk, enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3120 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3122 struct wined3d_unordered_access_view_vk *uav_vk;
3123 struct wined3d_unordered_access_view *uav;
3124 const VkDescriptorImageInfo *image_info;
3125 struct wined3d_resource *resource;
3126 struct wined3d_view_vk *view_vk;
3127 VkBufferView *buffer_view;
3128 VkDescriptorType type;
3130 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3132 FIXME("NULL unordered access views not implemented.\n");
3133 return false;
3135 resource = uav->resource;
3137 uav_vk = wined3d_unordered_access_view_vk(uav);
3138 view_vk = &uav_vk->view_vk;
3139 if (resource->type == WINED3D_RTYPE_BUFFER)
3141 image_info = NULL;
3142 buffer_view = &view_vk->u.vk_buffer_view;
3143 type = VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
3145 else
3147 struct wined3d_texture_vk *texture_vk = wined3d_texture_vk(texture_from_resource(resource));
3149 if (view_vk->u.vk_image_info.imageView)
3150 image_info = &view_vk->u.vk_image_info;
3151 else
3152 image_info = wined3d_texture_vk_get_default_image_info(texture_vk, context_vk);
3153 buffer_view = NULL;
3154 type = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
3157 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set,
3158 binding->binding_idx, type, NULL, image_info, buffer_view))
3159 return false;
3160 wined3d_context_vk_reference_unordered_access_view(context_vk, uav_vk);
3161 return true;
3164 static bool wined3d_shader_descriptor_writes_vk_add_uav_counter_write(
3165 struct wined3d_shader_descriptor_writes_vk *writes, struct wined3d_context_vk *context_vk,
3166 enum wined3d_pipeline pipeline, VkDescriptorSet vk_descriptor_set,
3167 const struct wined3d_state *state, const struct wined3d_shader_resource_binding *binding)
3169 struct wined3d_unordered_access_view_vk *uav_vk;
3170 struct wined3d_unordered_access_view *uav;
3172 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3174 FIXME("NULL unordered access view counters not implemented.\n");
3175 return false;
3178 uav_vk = wined3d_unordered_access_view_vk(uav);
3179 if (!uav_vk->vk_counter_view)
3180 return false;
3182 return wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3183 VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, NULL, NULL, &uav_vk->vk_counter_view);
3186 static bool wined3d_shader_descriptor_writes_vk_add_sampler_write(struct wined3d_shader_descriptor_writes_vk *writes,
3187 struct wined3d_context_vk *context_vk, VkDescriptorSet vk_descriptor_set, const struct wined3d_state *state,
3188 const struct wined3d_shader_resource_binding *binding)
3190 struct wined3d_sampler *sampler;
3192 if (!(sampler = state->sampler[binding->shader_type][binding->resource_idx]))
3193 sampler = context_vk->c.device->null_sampler;
3194 if (!wined3d_shader_descriptor_writes_vk_add_write(writes, vk_descriptor_set, binding->binding_idx,
3195 VK_DESCRIPTOR_TYPE_SAMPLER, NULL, &wined3d_sampler_vk(sampler)->vk_image_info, NULL))
3196 return false;
3197 wined3d_context_vk_reference_sampler(context_vk, wined3d_sampler_vk(sampler));
3198 return true;
3201 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk *context_vk,
3202 VkCommandBuffer vk_command_buffer, const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3204 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3205 VkDescriptorBufferInfo buffers[WINED3D_SHADER_TYPE_COUNT][MAX_CONSTANT_BUFFERS];
3206 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3207 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3208 const struct wined3d_shader_resource_binding *binding;
3209 struct wined3d_shader_resource_bindings *bindings;
3210 VkDescriptorSetLayout vk_set_layout;
3211 VkPipelineLayout vk_pipeline_layout;
3212 VkPipelineBindPoint vk_bind_point;
3213 VkDescriptorSet vk_descriptor_set;
3214 size_t i;
3216 switch (pipeline)
3218 case WINED3D_PIPELINE_GRAPHICS:
3219 bindings = &context_vk->graphics.bindings;
3220 vk_bind_point = VK_PIPELINE_BIND_POINT_GRAPHICS;
3221 vk_set_layout = context_vk->graphics.vk_set_layout;
3222 vk_pipeline_layout = context_vk->graphics.vk_pipeline_layout;
3223 break;
3225 case WINED3D_PIPELINE_COMPUTE:
3226 bindings = &context_vk->compute.bindings;
3227 vk_bind_point = VK_PIPELINE_BIND_POINT_COMPUTE;
3228 vk_set_layout = context_vk->compute.vk_set_layout;
3229 vk_pipeline_layout = context_vk->compute.vk_pipeline_layout;
3230 break;
3232 default:
3233 ERR("Invalid pipeline %#x.\n", pipeline);
3234 return false;
3237 if (!(vk_descriptor_set = wined3d_context_vk_create_vk_descriptor_set(context_vk, vk_set_layout)))
3239 WARN("Failed to create descriptor set.\n");
3240 return false;
3243 writes->count = 0;
3244 for (i = 0; i < bindings->count; ++i)
3246 binding = &bindings->bindings[i];
3248 switch (binding->shader_descriptor_type)
3250 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3251 if (!wined3d_shader_descriptor_writes_vk_add_cbv_write(writes, context_vk, vk_descriptor_set,
3252 state, binding, &buffers[binding->shader_type][binding->resource_idx]))
3253 return false;
3254 break;
3256 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3257 if (!wined3d_shader_descriptor_writes_vk_add_srv_write(writes,
3258 context_vk, vk_descriptor_set, state, binding))
3259 return false;
3260 break;
3262 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3263 if (!wined3d_shader_descriptor_writes_vk_add_uav_write(writes,
3264 context_vk, pipeline, vk_descriptor_set, state, binding))
3265 return false;
3266 break;
3268 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3269 if (!wined3d_shader_descriptor_writes_vk_add_uav_counter_write(writes,
3270 context_vk, pipeline, vk_descriptor_set, state, binding))
3271 return false;
3272 break;
3274 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3275 if (!wined3d_shader_descriptor_writes_vk_add_sampler_write(writes,
3276 context_vk, vk_descriptor_set, state, binding))
3277 return false;
3278 break;
3280 default:
3281 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3282 return false;
3286 VK_CALL(vkUpdateDescriptorSets(device_vk->vk_device, writes->count, writes->writes, 0, NULL));
3287 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer, vk_bind_point,
3288 vk_pipeline_layout, 0, 1, &vk_descriptor_set, 0, NULL));
3290 return true;
3293 static VkResult wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk *device_vk,
3294 const struct wined3d_vk_info *vk_info, const struct wined3d_pipeline_layout_key_vk *key,
3295 VkDescriptorSetLayout *vk_set_layout)
3297 VkDescriptorSetLayoutCreateInfo layout_desc;
3298 VkResult vr;
3300 layout_desc.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO;
3301 layout_desc.pNext = NULL;
3302 layout_desc.flags = 0;
3303 layout_desc.bindingCount = key->binding_count;
3304 layout_desc.pBindings = key->bindings;
3306 if ((vr = VK_CALL(vkCreateDescriptorSetLayout(device_vk->vk_device, &layout_desc, NULL, vk_set_layout))) < 0)
3307 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3309 return vr;
3312 struct wined3d_pipeline_layout_vk *wined3d_context_vk_get_pipeline_layout(
3313 struct wined3d_context_vk *context_vk, VkDescriptorSetLayoutBinding *bindings, SIZE_T binding_count)
3315 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3316 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3317 struct wined3d_pipeline_layout_key_vk key;
3318 struct wined3d_pipeline_layout_vk *layout;
3319 VkPipelineLayoutCreateInfo layout_desc;
3320 struct wine_rb_entry *entry;
3321 VkResult vr;
3323 key.bindings = bindings;
3324 key.binding_count = binding_count;
3325 if ((entry = wine_rb_get(&context_vk->pipeline_layouts, &key)))
3326 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_pipeline_layout_vk, entry);
3328 if (!(layout = heap_alloc(sizeof(*layout))))
3329 return NULL;
3331 if (!(layout->key.bindings = heap_alloc(sizeof(*layout->key.bindings) * key.binding_count)))
3333 heap_free(layout);
3334 return NULL;
3336 memcpy(layout->key.bindings, key.bindings, sizeof(*layout->key.bindings) * key.binding_count);
3337 layout->key.binding_count = key.binding_count;
3339 if ((vr = wined3d_context_vk_create_vk_descriptor_set_layout(device_vk, vk_info, &key, &layout->vk_set_layout)))
3341 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr));
3342 goto fail;
3345 layout_desc.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
3346 layout_desc.pNext = NULL;
3347 layout_desc.flags = 0;
3348 layout_desc.setLayoutCount = 1;
3349 layout_desc.pSetLayouts = &layout->vk_set_layout;
3350 layout_desc.pushConstantRangeCount = 0;
3351 layout_desc.pPushConstantRanges = NULL;
3353 if ((vr = VK_CALL(vkCreatePipelineLayout(device_vk->vk_device,
3354 &layout_desc, NULL, &layout->vk_pipeline_layout))) < 0)
3356 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr));
3357 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3358 goto fail;
3361 if (wine_rb_put(&context_vk->pipeline_layouts, &layout->key, &layout->entry) == -1)
3363 ERR("Failed to insert pipeline layout.\n");
3364 VK_CALL(vkDestroyPipelineLayout(device_vk->vk_device, layout->vk_pipeline_layout, NULL));
3365 VK_CALL(vkDestroyDescriptorSetLayout(device_vk->vk_device, layout->vk_set_layout, NULL));
3366 goto fail;
3369 return layout;
3371 fail:
3372 heap_free(layout->key.bindings);
3373 heap_free(layout);
3374 return NULL;
3377 static VkPipeline wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk *context_vk)
3379 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3380 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3381 struct wined3d_graphics_pipeline_vk *pipeline_vk;
3382 struct wined3d_graphics_pipeline_key_vk *key;
3383 struct wine_rb_entry *entry;
3384 VkResult vr;
3386 key = &context_vk->graphics.pipeline_key_vk;
3387 if ((entry = wine_rb_get(&context_vk->graphics_pipelines, key)))
3388 return WINE_RB_ENTRY_VALUE(entry, struct wined3d_graphics_pipeline_vk, entry)->vk_pipeline;
3390 if (!(pipeline_vk = heap_alloc(sizeof(*pipeline_vk))))
3391 return VK_NULL_HANDLE;
3392 pipeline_vk->key = *key;
3394 if ((vr = VK_CALL(vkCreateGraphicsPipelines(device_vk->vk_device,
3395 VK_NULL_HANDLE, 1, &key->pipeline_desc, NULL, &pipeline_vk->vk_pipeline))) < 0)
3397 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr));
3398 heap_free(pipeline_vk);
3399 return VK_NULL_HANDLE;
3402 if (wine_rb_put(&context_vk->graphics_pipelines, &pipeline_vk->key, &pipeline_vk->entry) == -1)
3403 ERR("Failed to insert pipeline.\n");
3405 return pipeline_vk->vk_pipeline;
3408 static void wined3d_context_vk_load_buffers(struct wined3d_context_vk *context_vk,
3409 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3411 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3412 struct wined3d_buffer_vk *buffer_vk;
3413 struct wined3d_buffer *buffer;
3414 unsigned int i;
3416 for (i = 0; i < ARRAY_SIZE(state->streams); ++i)
3418 if (!(buffer = state->streams[i].buffer))
3419 continue;
3421 buffer_vk = wined3d_buffer_vk(buffer);
3422 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3423 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_VERTEX_BUFFER);
3424 if (!buffer_vk->b.bo_user.valid)
3425 context_invalidate_state(&context_vk->c, STATE_STREAMSRC);
3428 if (use_transform_feedback(state) && vk_info->supported[WINED3D_VK_EXT_TRANSFORM_FEEDBACK])
3430 for (i = 0; i < ARRAY_SIZE(state->stream_output); ++i)
3432 if (!(buffer = state->stream_output[i].buffer))
3433 continue;
3435 wined3d_buffer_acquire_bo_for_write(buffer, &context_vk->c);
3437 buffer_vk = wined3d_buffer_vk(buffer);
3438 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3439 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_STREAM_OUTPUT);
3440 wined3d_buffer_invalidate_location(&buffer_vk->b, ~WINED3D_LOCATION_BUFFER);
3441 if (!buffer_vk->b.bo_user.valid)
3442 context_vk->update_stream_output = 1;
3444 context_vk->c.transform_feedback_active = 1;
3447 if (indexed || (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer))
3449 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3450 wined3d_buffer_load(&buffer_vk->b, &context_vk->c, state);
3451 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_INDEX_BUFFER);
3452 if (!buffer_vk->b.bo_user.valid)
3453 context_invalidate_state(&context_vk->c, STATE_INDEXBUFFER);
3456 if (indirect_vk)
3458 wined3d_buffer_load(&indirect_vk->b, &context_vk->c, state);
3459 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3463 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk *context_vk,
3464 const struct wined3d_state *state, enum wined3d_pipeline pipeline)
3466 struct wined3d_shader_descriptor_writes_vk *writes = &context_vk->descriptor_writes;
3467 const struct wined3d_shader_resource_bindings *bindings;
3468 const struct wined3d_shader_resource_binding *binding;
3469 struct wined3d_unordered_access_view_vk *uav_vk;
3470 struct wined3d_shader_resource_view_vk *srv_vk;
3471 struct wined3d_unordered_access_view *uav;
3472 struct wined3d_shader_resource_view *srv;
3473 struct wined3d_buffer_vk *buffer_vk;
3474 struct wined3d_buffer *buffer;
3475 size_t i;
3477 switch (pipeline)
3479 case WINED3D_PIPELINE_GRAPHICS:
3480 bindings = &context_vk->graphics.bindings;
3481 break;
3483 case WINED3D_PIPELINE_COMPUTE:
3484 bindings = &context_vk->compute.bindings;
3485 break;
3487 default:
3488 ERR("Invalid pipeline %#x.\n", pipeline);
3489 return;
3492 writes->count = 0;
3493 for (i = 0; i < bindings->count; ++i)
3495 binding = &bindings->bindings[i];
3497 switch (binding->shader_descriptor_type)
3499 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV:
3500 if (!(buffer = state->cb[binding->shader_type][binding->resource_idx].buffer))
3501 break;
3503 buffer_vk = wined3d_buffer_vk(buffer);
3504 wined3d_buffer_load(buffer, &context_vk->c, state);
3505 if (!buffer_vk->b.bo_user.valid)
3507 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3508 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_CONSTANT_BUFFER(binding->shader_type));
3509 else
3510 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER);
3512 wined3d_buffer_vk_barrier(buffer_vk, context_vk, WINED3D_BIND_CONSTANT_BUFFER);
3513 break;
3515 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV:
3516 if (!(srv = state->shader_resource_view[binding->shader_type][binding->resource_idx]))
3517 break;
3519 srv_vk = wined3d_shader_resource_view_vk(srv);
3520 if (srv->resource->type == WINED3D_RTYPE_BUFFER)
3522 if (!srv_vk->view_vk.bo_user.valid)
3524 wined3d_shader_resource_view_vk_update_buffer(srv_vk, context_vk);
3525 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3526 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING);
3527 else
3528 context_invalidate_compute_state(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING);
3530 wined3d_buffer_load(buffer_from_resource(srv->resource), &context_vk->c, state);
3532 else
3534 wined3d_texture_load(texture_from_resource(srv->resource), &context_vk->c, FALSE);
3536 wined3d_shader_resource_view_vk_barrier(srv_vk, context_vk, WINED3D_BIND_SHADER_RESOURCE);
3537 break;
3539 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV:
3540 if (!(uav = state->unordered_access_view[pipeline][binding->resource_idx]))
3541 break;
3543 uav_vk = wined3d_unordered_access_view_vk(uav);
3544 if (uav->resource->type == WINED3D_RTYPE_BUFFER)
3546 wined3d_buffer_acquire_bo_for_write(buffer_from_resource(uav->resource), &context_vk->c);
3547 if (!uav_vk->view_vk.bo_user.valid)
3549 wined3d_unordered_access_view_vk_update(uav_vk, context_vk);
3550 if (pipeline == WINED3D_PIPELINE_GRAPHICS)
3551 context_invalidate_state(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING);
3552 else
3553 context_invalidate_compute_state(&context_vk->c,
3554 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING);
3556 wined3d_buffer_load(buffer_from_resource(uav->resource), &context_vk->c, state);
3557 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_BUFFER);
3559 else
3561 wined3d_texture_load(texture_from_resource(uav->resource), &context_vk->c, FALSE);
3562 wined3d_unordered_access_view_invalidate_location(uav, ~WINED3D_LOCATION_TEXTURE_RGB);
3564 wined3d_unordered_access_view_vk_barrier(uav_vk, context_vk, WINED3D_BIND_UNORDERED_ACCESS);
3565 break;
3567 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER:
3568 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER:
3569 break;
3571 default:
3572 ERR("Invalid descriptor type %#x.\n", binding->shader_descriptor_type);
3573 break;
3578 static void wined3d_context_vk_prepare_used_rtv(struct wined3d_context_vk *context_vk, struct wined3d_rendertarget_view *rtv)
3580 if (wined3d_rendertarget_view_get_locations(rtv) & WINED3D_LOCATION_CLEARED)
3582 /* Need to restart render pass or the clear won't happen. */
3583 wined3d_context_vk_end_current_render_pass(context_vk);
3584 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3586 else
3588 wined3d_rendertarget_view_load_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3592 VkCommandBuffer wined3d_context_vk_apply_draw_state(struct wined3d_context_vk *context_vk,
3593 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk, bool indexed)
3595 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3596 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3597 const struct wined3d_blend_state *b = state->blend_state;
3598 bool dual_source_blend = b && b->dual_source;
3599 struct wined3d_rendertarget_view *dsv;
3600 struct wined3d_rendertarget_view *rtv;
3601 struct wined3d_buffer_vk *buffer_vk;
3602 VkSampleCountFlagBits sample_count;
3603 VkCommandBuffer vk_command_buffer;
3604 unsigned int i, invalidate_rt = 0;
3605 uint32_t null_buffer_binding;
3606 bool invalidate_ds = false;
3608 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL))
3609 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER)
3610 || dual_source_blend != context_vk->c.last_was_dual_source_blend)
3612 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_PIXEL);
3613 context_vk->c.last_was_dual_source_blend = dual_source_blend;
3615 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX)))
3616 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_VERTEX);
3617 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY)))
3618 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_GEOMETRY);
3619 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_HULL)))
3620 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_HULL) | (1u << WINED3D_SHADER_TYPE_DOMAIN);
3621 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN)))
3622 context_vk->c.shader_update_mask |= (1u << WINED3D_SHADER_TYPE_DOMAIN);
3624 context_vk->sample_count = 0;
3625 for (i = 0; i < ARRAY_SIZE(state->fb.render_targets); ++i)
3627 if (!(rtv = state->fb.render_targets[i]) || rtv->format->id == WINED3DFMT_NULL)
3628 continue;
3630 if (wined3d_blend_state_get_writemask(state->blend_state, i))
3632 /* We handle clears at the beginning of the render pass, no need for an explicit clear
3633 * first. */
3634 wined3d_context_vk_prepare_used_rtv(context_vk, rtv);
3635 invalidate_rt |= (1 << i);
3637 else
3639 wined3d_rendertarget_view_prepare_location(rtv, &context_vk->c, rtv->resource->draw_binding);
3642 sample_count = max(1, wined3d_resource_get_sample_count(rtv->resource));
3643 if (!context_vk->sample_count)
3644 context_vk->sample_count = sample_count;
3645 else if (context_vk->sample_count != sample_count)
3646 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3649 if ((dsv = state->fb.depth_stencil))
3651 if (wined3d_state_uses_depth_buffer(state))
3652 wined3d_context_vk_prepare_used_rtv(context_vk, dsv);
3653 else
3654 wined3d_rendertarget_view_prepare_location(dsv, &context_vk->c, dsv->resource->draw_binding);
3656 if (!state->depth_stencil_state || state->depth_stencil_state->writes_ds)
3657 invalidate_ds = true;
3659 sample_count = max(1, wined3d_resource_get_sample_count(dsv->resource));
3660 if (!context_vk->sample_count)
3661 context_vk->sample_count = sample_count;
3662 else if (context_vk->sample_count != sample_count)
3663 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk->sample_count, sample_count);
3666 if (!context_vk->sample_count)
3667 context_vk->sample_count = VK_SAMPLE_COUNT_1_BIT;
3668 if (context_vk->c.shader_update_mask & ~(1u << WINED3D_SHADER_TYPE_COMPUTE))
3670 device_vk->d.shader_backend->shader_select(device_vk->d.shader_priv, &context_vk->c, state);
3671 if (!context_vk->graphics.vk_pipeline_layout)
3673 ERR("No pipeline layout set.\n");
3674 return VK_NULL_HANDLE;
3676 context_vk->c.update_shader_resource_bindings = 1;
3677 context_vk->c.update_unordered_access_view_bindings = 1;
3680 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_GRAPHICS);
3682 wined3d_context_vk_load_buffers(context_vk, state, indirect_vk, indexed);
3684 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3686 ERR("Failed to get command buffer.\n");
3687 return VK_NULL_HANDLE;
3690 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_FRAMEBUFFER))
3691 wined3d_context_vk_end_current_render_pass(context_vk);
3692 if (!wined3d_context_vk_begin_render_pass(context_vk, vk_command_buffer, state, vk_info))
3694 ERR("Failed to begin render pass.\n");
3695 return VK_NULL_HANDLE;
3698 while (invalidate_rt)
3700 i = wined3d_bit_scan(&invalidate_rt);
3701 rtv = state->fb.render_targets[i];
3702 wined3d_rendertarget_view_validate_location(rtv, rtv->resource->draw_binding);
3703 wined3d_rendertarget_view_invalidate_location(rtv, ~rtv->resource->draw_binding);
3706 if (invalidate_ds)
3708 wined3d_rendertarget_view_validate_location(dsv, dsv->resource->draw_binding);
3709 wined3d_rendertarget_view_invalidate_location(dsv, ~dsv->resource->draw_binding);
3712 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk, state, context_vk->graphics.vk_pipeline_layout,
3713 &null_buffer_binding) || !context_vk->graphics.vk_pipeline)
3715 if (!(context_vk->graphics.vk_pipeline = wined3d_context_vk_get_graphics_pipeline(context_vk)))
3717 ERR("Failed to get graphics pipeline.\n");
3718 return VK_NULL_HANDLE;
3721 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3722 VK_PIPELINE_BIND_POINT_GRAPHICS, context_vk->graphics.vk_pipeline));
3723 if (null_buffer_binding != ~0u)
3725 VkDeviceSize offset = 0;
3726 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer, null_buffer_binding, 1,
3727 &device_vk->null_resources_vk.buffer_info.buffer, &offset));
3731 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STENCIL_REF) && dsv)
3733 VK_CALL(vkCmdSetStencilReference(vk_command_buffer, VK_STENCIL_FACE_FRONT_AND_BACK,
3734 state->stencil_ref & wined3d_mask_from_size(dsv->format->stencil_size)));
3737 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAMSRC))
3738 wined3d_context_vk_bind_vertex_buffers(context_vk, vk_command_buffer, state, vk_info);
3740 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_STREAM_OUTPUT))
3742 context_vk->update_stream_output = 1;
3743 context_vk->c.transform_feedback_paused = 0;
3745 if (context_vk->c.transform_feedback_active && context_vk->update_stream_output)
3747 wined3d_context_vk_bind_stream_output_buffers(context_vk, vk_command_buffer, state, vk_info);
3748 context_vk->update_stream_output = 0;
3751 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_INDEXBUFFER) && state->index_buffer)
3753 const VkDescriptorBufferInfo *buffer_info;
3754 VkIndexType idx_type;
3756 if (state->index_format == WINED3DFMT_R16_UINT)
3757 idx_type = VK_INDEX_TYPE_UINT16;
3758 else
3759 idx_type = VK_INDEX_TYPE_UINT32;
3760 buffer_vk = wined3d_buffer_vk(state->index_buffer);
3761 buffer_info = wined3d_buffer_vk_get_buffer_info(buffer_vk);
3762 wined3d_context_vk_reference_bo(context_vk, wined3d_bo_vk(buffer_vk->b.buffer_object));
3763 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer, buffer_info->buffer,
3764 buffer_info->offset + state->index_offset, idx_type));
3767 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL))
3768 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3769 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX))
3770 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3771 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY))
3772 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3773 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL))
3774 || wined3d_context_is_graphics_state_dirty(&context_vk->c,
3775 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN))
3776 || wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_SHADER_RESOURCE_BINDING))
3777 context_vk->c.update_shader_resource_bindings = 1;
3778 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING))
3779 context_vk->c.update_unordered_access_view_bindings = 1;
3781 if (context_vk->c.update_shader_resource_bindings || context_vk->c.update_unordered_access_view_bindings)
3783 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_GRAPHICS))
3785 ERR("Failed to update shader descriptors.\n");
3786 return VK_NULL_HANDLE;
3789 context_vk->c.update_shader_resource_bindings = 0;
3790 context_vk->c.update_unordered_access_view_bindings = 0;
3793 if (wined3d_context_is_graphics_state_dirty(&context_vk->c, STATE_BLEND_FACTOR))
3794 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer, &state->blend_factor.r));
3796 memset(context_vk->c.dirty_graphics_states, 0, sizeof(context_vk->c.dirty_graphics_states));
3797 context_vk->c.shader_update_mask &= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3799 return vk_command_buffer;
3802 VkCommandBuffer wined3d_context_vk_apply_compute_state(struct wined3d_context_vk *context_vk,
3803 const struct wined3d_state *state, struct wined3d_buffer_vk *indirect_vk)
3805 struct wined3d_device_vk *device_vk = wined3d_device_vk(context_vk->c.device);
3806 const struct wined3d_vk_info *vk_info = context_vk->vk_info;
3807 VkCommandBuffer vk_command_buffer;
3809 wined3d_context_vk_end_current_render_pass(context_vk);
3811 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER))
3812 context_vk->c.shader_update_mask |= 1u << WINED3D_SHADER_TYPE_COMPUTE;
3814 if (context_vk->c.shader_update_mask & (1u << WINED3D_SHADER_TYPE_COMPUTE))
3816 device_vk->d.shader_backend->shader_select_compute(device_vk->d.shader_priv, &context_vk->c, state);
3817 if (!context_vk->compute.vk_pipeline)
3819 ERR("No compute pipeline set.\n");
3820 return VK_NULL_HANDLE;
3822 context_vk->c.update_compute_shader_resource_bindings = 1;
3823 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3824 context_vk->update_compute_pipeline = 1;
3827 wined3d_context_vk_load_shader_resources(context_vk, state, WINED3D_PIPELINE_COMPUTE);
3829 if (indirect_vk)
3831 wined3d_buffer_load_location(&indirect_vk->b, &context_vk->c, WINED3D_LOCATION_BUFFER);
3832 wined3d_buffer_vk_barrier(indirect_vk, context_vk, WINED3D_BIND_INDIRECT_BUFFER);
3835 if (!(vk_command_buffer = wined3d_context_vk_get_command_buffer(context_vk)))
3837 ERR("Failed to get command buffer.\n");
3838 return VK_NULL_HANDLE;
3841 if (context_vk->update_compute_pipeline)
3843 VK_CALL(vkCmdBindPipeline(vk_command_buffer,
3844 VK_PIPELINE_BIND_POINT_COMPUTE, context_vk->compute.vk_pipeline));
3845 context_vk->update_compute_pipeline = 0;
3848 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_CONSTANT_BUFFER)
3849 || wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_SHADER_RESOURCE_BINDING))
3850 context_vk->c.update_compute_shader_resource_bindings = 1;
3851 if (wined3d_context_is_compute_state_dirty(&context_vk->c, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING))
3852 context_vk->c.update_compute_unordered_access_view_bindings = 1;
3854 if (context_vk->c.update_compute_shader_resource_bindings
3855 || context_vk->c.update_compute_unordered_access_view_bindings)
3857 if (!wined3d_context_vk_update_descriptors(context_vk, vk_command_buffer, state, WINED3D_PIPELINE_COMPUTE))
3859 ERR("Failed to update shader descriptors.\n");
3860 return VK_NULL_HANDLE;
3863 context_vk->c.update_compute_shader_resource_bindings = 0;
3864 context_vk->c.update_compute_unordered_access_view_bindings = 0;
3867 memset(context_vk->c.dirty_compute_states, 0, sizeof(context_vk->c.dirty_compute_states));
3868 context_vk->c.shader_update_mask &= ~(1u << WINED3D_SHADER_TYPE_COMPUTE);
3870 return vk_command_buffer;
3873 HRESULT wined3d_context_vk_init(struct wined3d_context_vk *context_vk, struct wined3d_swapchain *swapchain)
3875 VkCommandPoolCreateInfo command_pool_info;
3876 const struct wined3d_vk_info *vk_info;
3877 struct wined3d_adapter_vk *adapter_vk;
3878 struct wined3d_device_vk *device_vk;
3879 VkResult vr;
3881 TRACE("context_vk %p, swapchain %p.\n", context_vk, swapchain);
3883 memset(context_vk, 0, sizeof(*context_vk));
3884 wined3d_context_init(&context_vk->c, swapchain);
3885 device_vk = wined3d_device_vk(swapchain->device);
3886 adapter_vk = wined3d_adapter_vk(device_vk->d.adapter);
3887 context_vk->vk_info = vk_info = &adapter_vk->vk_info;
3889 command_pool_info.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO;
3890 command_pool_info.pNext = NULL;
3891 command_pool_info.flags = VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
3892 command_pool_info.queueFamilyIndex = device_vk->vk_queue_family_index;
3893 if ((vr = VK_CALL(vkCreateCommandPool(device_vk->vk_device,
3894 &command_pool_info, NULL, &context_vk->vk_command_pool))) < 0)
3896 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr));
3897 wined3d_context_cleanup(&context_vk->c);
3898 return E_FAIL;
3900 context_vk->current_command_buffer.id = 1;
3902 wined3d_context_vk_init_graphics_pipeline_key(context_vk);
3904 list_init(&context_vk->render_pass_queries);
3905 list_init(&context_vk->active_queries);
3906 list_init(&context_vk->completed_query_pools);
3907 list_init(&context_vk->free_occlusion_query_pools);
3908 list_init(&context_vk->free_timestamp_query_pools);
3909 list_init(&context_vk->free_pipeline_statistics_query_pools);
3910 list_init(&context_vk->free_stream_output_statistics_query_pools);
3912 wine_rb_init(&context_vk->render_passes, wined3d_render_pass_vk_compare);
3913 wine_rb_init(&context_vk->pipeline_layouts, wined3d_pipeline_layout_vk_compare);
3914 wine_rb_init(&context_vk->graphics_pipelines, wined3d_graphics_pipeline_vk_compare);
3915 wine_rb_init(&context_vk->bo_slab_available, wined3d_bo_slab_vk_compare);
3917 return WINED3D_OK;