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