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