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