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
26 #include "wine/port.h"
28 #include "wined3d_private.h"
30 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
32 VkCompareOp
vk_compare_op_from_wined3d(enum wined3d_cmp_func op
)
36 case WINED3D_CMP_NEVER
:
37 return VK_COMPARE_OP_NEVER
;
38 case WINED3D_CMP_LESS
:
39 return VK_COMPARE_OP_LESS
;
40 case WINED3D_CMP_EQUAL
:
41 return VK_COMPARE_OP_EQUAL
;
42 case WINED3D_CMP_LESSEQUAL
:
43 return VK_COMPARE_OP_LESS_OR_EQUAL
;
44 case WINED3D_CMP_GREATER
:
45 return VK_COMPARE_OP_GREATER
;
46 case WINED3D_CMP_NOTEQUAL
:
47 return VK_COMPARE_OP_NOT_EQUAL
;
48 case WINED3D_CMP_GREATEREQUAL
:
49 return VK_COMPARE_OP_GREATER_OR_EQUAL
;
50 case WINED3D_CMP_ALWAYS
:
51 return VK_COMPARE_OP_ALWAYS
;
54 WARN("Unhandled compare operation %#x.\n", op
);
56 FIXME("Unhandled compare operation %#x.\n", op
);
57 return VK_COMPARE_OP_NEVER
;
61 VkShaderStageFlagBits
vk_shader_stage_from_wined3d(enum wined3d_shader_type shader_type
)
65 case WINED3D_SHADER_TYPE_VERTEX
:
66 return VK_SHADER_STAGE_VERTEX_BIT
;
67 case WINED3D_SHADER_TYPE_HULL
:
68 return VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT
;
69 case WINED3D_SHADER_TYPE_DOMAIN
:
70 return VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT
;
71 case WINED3D_SHADER_TYPE_GEOMETRY
:
72 return VK_SHADER_STAGE_GEOMETRY_BIT
;
73 case WINED3D_SHADER_TYPE_PIXEL
:
74 return VK_SHADER_STAGE_FRAGMENT_BIT
;
75 case WINED3D_SHADER_TYPE_COMPUTE
:
76 return VK_SHADER_STAGE_COMPUTE_BIT
;
78 ERR("Unhandled shader type %s.\n", debug_shader_type(shader_type
));
83 static VkBlendFactor
vk_blend_factor_from_wined3d(enum wined3d_blend blend
,
84 const struct wined3d_format
*dst_format
, bool alpha
)
88 case WINED3D_BLEND_ZERO
:
89 return VK_BLEND_FACTOR_ZERO
;
90 case WINED3D_BLEND_ONE
:
91 return VK_BLEND_FACTOR_ONE
;
92 case WINED3D_BLEND_SRCCOLOR
:
93 return VK_BLEND_FACTOR_SRC_COLOR
;
94 case WINED3D_BLEND_INVSRCCOLOR
:
95 return VK_BLEND_FACTOR_ONE_MINUS_SRC_COLOR
;
96 case WINED3D_BLEND_SRCALPHA
:
97 return VK_BLEND_FACTOR_SRC_ALPHA
;
98 case WINED3D_BLEND_INVSRCALPHA
:
99 return VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA
;
100 case WINED3D_BLEND_DESTALPHA
:
101 if (dst_format
->alpha_size
)
102 return VK_BLEND_FACTOR_DST_ALPHA
;
103 return VK_BLEND_FACTOR_ONE
;
104 case WINED3D_BLEND_INVDESTALPHA
:
105 if (dst_format
->alpha_size
)
106 return VK_BLEND_FACTOR_ONE_MINUS_DST_ALPHA
;
107 return VK_BLEND_FACTOR_ZERO
;
108 case WINED3D_BLEND_DESTCOLOR
:
109 return VK_BLEND_FACTOR_DST_COLOR
;
110 case WINED3D_BLEND_INVDESTCOLOR
:
111 return VK_BLEND_FACTOR_ONE_MINUS_DST_COLOR
;
112 case WINED3D_BLEND_SRCALPHASAT
:
113 return VK_BLEND_FACTOR_SRC_ALPHA_SATURATE
;
114 case WINED3D_BLEND_BLENDFACTOR
:
116 return VK_BLEND_FACTOR_CONSTANT_ALPHA
;
117 return VK_BLEND_FACTOR_CONSTANT_COLOR
;
118 case WINED3D_BLEND_INVBLENDFACTOR
:
120 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_ALPHA
;
121 return VK_BLEND_FACTOR_ONE_MINUS_CONSTANT_COLOR
;
122 case WINED3D_BLEND_SRC1COLOR
:
123 return VK_BLEND_FACTOR_SRC1_COLOR
;
124 case WINED3D_BLEND_INVSRC1COLOR
:
125 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_COLOR
;
126 case WINED3D_BLEND_SRC1ALPHA
:
127 return VK_BLEND_FACTOR_SRC1_ALPHA
;
128 case WINED3D_BLEND_INVSRC1ALPHA
:
129 return VK_BLEND_FACTOR_ONE_MINUS_SRC1_ALPHA
;
131 FIXME("Unhandled blend %#x.\n", blend
);
132 return VK_BLEND_FACTOR_ZERO
;
136 static VkBlendOp
vk_blend_op_from_wined3d(enum wined3d_blend_op op
)
140 case WINED3D_BLEND_OP_ADD
:
141 return VK_BLEND_OP_ADD
;
142 case WINED3D_BLEND_OP_SUBTRACT
:
143 return VK_BLEND_OP_SUBTRACT
;
144 case WINED3D_BLEND_OP_REVSUBTRACT
:
145 return VK_BLEND_OP_REVERSE_SUBTRACT
;
146 case WINED3D_BLEND_OP_MIN
:
147 return VK_BLEND_OP_MIN
;
148 case WINED3D_BLEND_OP_MAX
:
149 return VK_BLEND_OP_MAX
;
151 FIXME("Unhandled blend op %#x.\n", op
);
152 return VK_BLEND_OP_ADD
;
156 static VkColorComponentFlags
vk_colour_write_mask_from_wined3d(uint32_t wined3d_mask
)
158 VkColorComponentFlags vk_mask
= 0;
160 if (wined3d_mask
& WINED3DCOLORWRITEENABLE_RED
)
161 vk_mask
|= VK_COLOR_COMPONENT_R_BIT
;
162 if (wined3d_mask
& WINED3DCOLORWRITEENABLE_GREEN
)
163 vk_mask
|= VK_COLOR_COMPONENT_G_BIT
;
164 if (wined3d_mask
& WINED3DCOLORWRITEENABLE_BLUE
)
165 vk_mask
|= VK_COLOR_COMPONENT_B_BIT
;
166 if (wined3d_mask
& WINED3DCOLORWRITEENABLE_ALPHA
)
167 vk_mask
|= VK_COLOR_COMPONENT_A_BIT
;
172 static VkCullModeFlags
vk_cull_mode_from_wined3d(enum wined3d_cull mode
)
176 case WINED3D_CULL_NONE
:
177 return VK_CULL_MODE_NONE
;
178 case WINED3D_CULL_FRONT
:
179 return VK_CULL_MODE_FRONT_BIT
;
180 case WINED3D_CULL_BACK
:
181 return VK_CULL_MODE_BACK_BIT
;
183 FIXME("Unhandled cull mode %#x.\n", mode
);
184 return VK_CULL_MODE_NONE
;
188 static VkPrimitiveTopology
vk_topology_from_wined3d(enum wined3d_primitive_type t
)
192 case WINED3D_PT_POINTLIST
:
193 return VK_PRIMITIVE_TOPOLOGY_POINT_LIST
;
194 case WINED3D_PT_LINELIST
:
195 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST
;
196 case WINED3D_PT_LINESTRIP
:
197 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
;
198 case WINED3D_PT_TRIANGLELIST
:
199 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
;
200 case WINED3D_PT_TRIANGLESTRIP
:
201 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
;
202 case WINED3D_PT_TRIANGLEFAN
:
203 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
;
204 case WINED3D_PT_LINELIST_ADJ
:
205 return VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
;
206 case WINED3D_PT_LINESTRIP_ADJ
:
207 return VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
;
208 case WINED3D_PT_TRIANGLELIST_ADJ
:
209 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
;
210 case WINED3D_PT_TRIANGLESTRIP_ADJ
:
211 return VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
;
212 case WINED3D_PT_PATCH
:
213 return VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
;
215 FIXME("Unhandled primitive type %s.\n", debug_d3dprimitivetype(t
));
216 case WINED3D_PT_UNDEFINED
:
221 static VkStencilOp
vk_stencil_op_from_wined3d(enum wined3d_stencil_op op
)
225 case WINED3D_STENCIL_OP_KEEP
:
226 return VK_STENCIL_OP_KEEP
;
227 case WINED3D_STENCIL_OP_ZERO
:
228 return VK_STENCIL_OP_ZERO
;
229 case WINED3D_STENCIL_OP_REPLACE
:
230 return VK_STENCIL_OP_REPLACE
;
231 case WINED3D_STENCIL_OP_INCR_SAT
:
232 return VK_STENCIL_OP_INCREMENT_AND_CLAMP
;
233 case WINED3D_STENCIL_OP_DECR_SAT
:
234 return VK_STENCIL_OP_DECREMENT_AND_CLAMP
;
235 case WINED3D_STENCIL_OP_INVERT
:
236 return VK_STENCIL_OP_INVERT
;
237 case WINED3D_STENCIL_OP_INCR
:
238 return VK_STENCIL_OP_INCREMENT_AND_WRAP
;
239 case WINED3D_STENCIL_OP_DECR
:
240 return VK_STENCIL_OP_DECREMENT_AND_WRAP
;
243 WARN("Unhandled stencil operation %#x.\n", op
);
245 FIXME("Unhandled stencil operation %#x.\n", op
);
246 return VK_STENCIL_OP_KEEP
;
250 void *wined3d_allocator_chunk_vk_map(struct wined3d_allocator_chunk_vk
*chunk_vk
,
251 struct wined3d_context_vk
*context_vk
)
253 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
254 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
257 TRACE("chunk %p, memory 0x%s, map_ptr %p.\n", chunk_vk
,
258 wine_dbgstr_longlong(chunk_vk
->vk_memory
), chunk_vk
->c
.map_ptr
);
260 if (!chunk_vk
->c
.map_ptr
&& (vr
= VK_CALL(vkMapMemory(device_vk
->vk_device
,
261 chunk_vk
->vk_memory
, 0, VK_WHOLE_SIZE
, 0, &chunk_vk
->c
.map_ptr
))) < 0)
263 ERR("Failed to map chunk memory, vr %s.\n", wined3d_debug_vkresult(vr
));
267 ++chunk_vk
->c
.map_count
;
269 return chunk_vk
->c
.map_ptr
;
272 void wined3d_allocator_chunk_vk_unmap(struct wined3d_allocator_chunk_vk
*chunk_vk
,
273 struct wined3d_context_vk
*context_vk
)
275 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
276 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
278 TRACE("chunk_vk %p, context_vk %p.\n", chunk_vk
, context_vk
);
280 if (--chunk_vk
->c
.map_count
)
283 VK_CALL(vkUnmapMemory(device_vk
->vk_device
, chunk_vk
->vk_memory
));
284 chunk_vk
->c
.map_ptr
= NULL
;
287 VkDeviceMemory
wined3d_context_vk_allocate_vram_chunk_memory(struct wined3d_context_vk
*context_vk
,
288 unsigned int pool
, size_t size
)
290 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
291 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
292 VkMemoryAllocateInfo allocate_info
;
293 VkDeviceMemory vk_memory
;
296 allocate_info
.sType
= VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO
;
297 allocate_info
.pNext
= NULL
;
298 allocate_info
.allocationSize
= size
;
299 allocate_info
.memoryTypeIndex
= pool
;
300 if ((vr
= VK_CALL(vkAllocateMemory(device_vk
->vk_device
, &allocate_info
, NULL
, &vk_memory
))) < 0)
302 ERR("Failed to allocate memory, vr %s.\n", wined3d_debug_vkresult(vr
));
303 return VK_NULL_HANDLE
;
309 struct wined3d_allocator_block
*wined3d_context_vk_allocate_memory(struct wined3d_context_vk
*context_vk
,
310 unsigned int memory_type
, VkDeviceSize size
, VkDeviceMemory
*vk_memory
)
312 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
313 struct wined3d_allocator
*allocator
= &device_vk
->allocator
;
314 struct wined3d_allocator_block
*block
;
316 if (size
> WINED3D_ALLOCATOR_CHUNK_SIZE
/ 2)
318 *vk_memory
= wined3d_context_vk_allocate_vram_chunk_memory(context_vk
, memory_type
, size
);
322 if (!(block
= wined3d_allocator_allocate(allocator
, &context_vk
->c
, memory_type
, size
)))
324 *vk_memory
= VK_NULL_HANDLE
;
328 *vk_memory
= wined3d_allocator_chunk_vk(block
->chunk
)->vk_memory
;
333 static bool wined3d_context_vk_create_slab_bo(struct wined3d_context_vk
*context_vk
,
334 VkDeviceSize size
, VkBufferUsageFlags usage
, VkMemoryPropertyFlags memory_type
, struct wined3d_bo_vk
*bo
)
336 const struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk(context_vk
->c
.device
->adapter
);
337 const VkPhysicalDeviceLimits
*limits
= &adapter_vk
->device_limits
;
338 struct wined3d_bo_slab_vk_key key
;
339 struct wined3d_bo_slab_vk
*slab
;
340 struct wine_rb_entry
*entry
;
341 size_t object_size
, idx
;
344 if (size
> WINED3D_ALLOCATOR_MIN_BLOCK_SIZE
/ 2)
347 alignment
= WINED3D_SLAB_BO_MIN_OBJECT_ALIGN
;
348 if ((usage
& (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
| VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
))
349 && limits
->minTexelBufferOffsetAlignment
> alignment
)
350 alignment
= limits
->minTexelBufferOffsetAlignment
;
351 if ((usage
& VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
) && limits
->minUniformBufferOffsetAlignment
)
352 alignment
= limits
->minUniformBufferOffsetAlignment
;
353 if ((usage
& VK_BUFFER_USAGE_STORAGE_BUFFER_BIT
) && limits
->minStorageBufferOffsetAlignment
)
354 alignment
= limits
->minStorageBufferOffsetAlignment
;
356 object_size
= (size
+ (alignment
- 1)) & ~(alignment
- 1);
357 if (object_size
< WINED3D_ALLOCATOR_MIN_BLOCK_SIZE
/ 32)
358 object_size
= WINED3D_ALLOCATOR_MIN_BLOCK_SIZE
/ 32;
359 key
.memory_type
= memory_type
;
361 key
.size
= 32 * object_size
;
363 if ((entry
= wine_rb_get(&context_vk
->bo_slab_available
, &key
)))
365 slab
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_bo_slab_vk
, entry
);
366 TRACE("Using existing bo slab %p.\n", slab
);
370 if (!(slab
= heap_alloc_zero(sizeof(*slab
))))
372 ERR("Failed to allocate bo slab.\n");
376 slab
->requested_memory_type
= memory_type
;
377 if (!wined3d_context_vk_create_bo(context_vk
, key
.size
, usage
, memory_type
, &slab
->bo
))
379 ERR("Failed to create slab bo.\n");
385 if (wine_rb_put(&context_vk
->bo_slab_available
, &key
, &slab
->entry
) < 0)
387 ERR("Failed to add slab to available tree.\n");
388 wined3d_context_vk_destroy_bo(context_vk
, &slab
->bo
);
393 TRACE("Created new bo slab %p.\n", slab
);
396 idx
= wined3d_bit_scan(&slab
->map
);
401 wine_rb_replace(&context_vk
->bo_slab_available
, &slab
->entry
, &slab
->next
->entry
);
406 wine_rb_remove(&context_vk
->bo_slab_available
, &slab
->entry
);
413 bo
->buffer_offset
= idx
* object_size
;
414 bo
->memory_offset
= slab
->bo
.memory_offset
+ bo
->buffer_offset
;
416 list_init(&bo
->users
);
417 bo
->command_buffer_id
= 0;
419 TRACE("Using buffer 0x%s, memory 0x%s, offset 0x%s for bo %p.\n",
420 wine_dbgstr_longlong(bo
->vk_buffer
), wine_dbgstr_longlong(bo
->vk_memory
),
421 wine_dbgstr_longlong(bo
->buffer_offset
), bo
);
426 BOOL
wined3d_context_vk_create_bo(struct wined3d_context_vk
*context_vk
, VkDeviceSize size
,
427 VkBufferUsageFlags usage
, VkMemoryPropertyFlags memory_type
, struct wined3d_bo_vk
*bo
)
429 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
430 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
431 VkMemoryRequirements memory_requirements
;
432 struct wined3d_adapter_vk
*adapter_vk
;
433 VkBufferCreateInfo create_info
;
434 unsigned int memory_type_idx
;
437 if (wined3d_context_vk_create_slab_bo(context_vk
, size
, usage
, memory_type
, bo
))
440 adapter_vk
= wined3d_adapter_vk(device_vk
->d
.adapter
);
442 create_info
.sType
= VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO
;
443 create_info
.pNext
= NULL
;
444 create_info
.flags
= 0;
445 create_info
.size
= size
;
446 create_info
.usage
= usage
;
447 create_info
.sharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
448 create_info
.queueFamilyIndexCount
= 0;
449 create_info
.pQueueFamilyIndices
= NULL
;
451 if ((vr
= VK_CALL(vkCreateBuffer(device_vk
->vk_device
, &create_info
, NULL
, &bo
->vk_buffer
))) < 0)
453 ERR("Failed to create Vulkan buffer, vr %s.\n", wined3d_debug_vkresult(vr
));
457 VK_CALL(vkGetBufferMemoryRequirements(device_vk
->vk_device
, bo
->vk_buffer
, &memory_requirements
));
459 memory_type_idx
= wined3d_adapter_vk_get_memory_type_index(adapter_vk
,
460 memory_requirements
.memoryTypeBits
, memory_type
);
461 if (memory_type_idx
== ~0u)
463 ERR("Failed to find suitable memory type.\n");
464 VK_CALL(vkDestroyBuffer(device_vk
->vk_device
, bo
->vk_buffer
, NULL
));
467 bo
->memory
= wined3d_context_vk_allocate_memory(context_vk
,
468 memory_type_idx
, memory_requirements
.size
, &bo
->vk_memory
);
471 ERR("Failed to allocate buffer memory.\n");
472 VK_CALL(vkDestroyBuffer(device_vk
->vk_device
, bo
->vk_buffer
, NULL
));
475 bo
->memory_offset
= bo
->memory
? bo
->memory
->offset
: 0;
477 if ((vr
= VK_CALL(vkBindBufferMemory(device_vk
->vk_device
, bo
->vk_buffer
,
478 bo
->vk_memory
, bo
->memory_offset
))) < 0)
480 ERR("Failed to bind buffer memory, vr %s.\n", wined3d_debug_vkresult(vr
));
482 wined3d_allocator_block_free(bo
->memory
);
484 VK_CALL(vkFreeMemory(device_vk
->vk_device
, bo
->vk_memory
, NULL
));
485 VK_CALL(vkDestroyBuffer(device_vk
->vk_device
, bo
->vk_buffer
, NULL
));
490 bo
->buffer_offset
= 0;
493 bo
->memory_type
= adapter_vk
->memory_properties
.memoryTypes
[memory_type_idx
].propertyFlags
;
494 list_init(&bo
->users
);
495 bo
->command_buffer_id
= 0;
498 TRACE("Created buffer 0x%s, memory 0x%s for bo %p.\n",
499 wine_dbgstr_longlong(bo
->vk_buffer
), wine_dbgstr_longlong(bo
->vk_memory
), bo
);
504 BOOL
wined3d_context_vk_create_image(struct wined3d_context_vk
*context_vk
, VkImageType vk_image_type
,
505 VkImageUsageFlags usage
, VkFormat vk_format
, unsigned int width
, unsigned int height
, unsigned int depth
,
506 unsigned int sample_count
, unsigned int mip_levels
, unsigned int layer_count
, unsigned int flags
,
507 struct wined3d_image_vk
*image
)
509 struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk(context_vk
->c
.device
->adapter
);
510 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
511 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
512 VkMemoryRequirements memory_requirements
;
513 VkImageCreateInfo create_info
;
514 unsigned int memory_type_idx
;
517 create_info
.sType
= VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO
;
518 create_info
.pNext
= NULL
;
519 create_info
.flags
= flags
;
520 create_info
.imageType
= vk_image_type
;
521 create_info
.format
= vk_format
;
522 create_info
.extent
.width
= width
;
523 create_info
.extent
.height
= height
;
524 create_info
.extent
.depth
= depth
;
525 create_info
.mipLevels
= mip_levels
;
526 create_info
.arrayLayers
= layer_count
;
527 create_info
.samples
= sample_count
;
528 create_info
.tiling
= VK_IMAGE_TILING_OPTIMAL
;
529 create_info
.usage
= usage
;
530 create_info
.sharingMode
= VK_SHARING_MODE_EXCLUSIVE
;
531 create_info
.queueFamilyIndexCount
= 0;
532 create_info
.pQueueFamilyIndices
= NULL
;
533 create_info
.initialLayout
= VK_IMAGE_LAYOUT_UNDEFINED
;
535 image
->command_buffer_id
= 0;
537 vr
= VK_CALL(vkCreateImage(device_vk
->vk_device
, &create_info
, NULL
, &image
->vk_image
));
538 if (vr
!= VK_SUCCESS
)
540 ERR("Failed to create image, vr %s.\n", wined3d_debug_vkresult(vr
));
541 image
->vk_image
= VK_NULL_HANDLE
;
545 VK_CALL(vkGetImageMemoryRequirements(device_vk
->vk_device
, image
->vk_image
,
546 &memory_requirements
));
548 memory_type_idx
= wined3d_adapter_vk_get_memory_type_index(adapter_vk
,
549 memory_requirements
.memoryTypeBits
, VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
);
550 if (memory_type_idx
== ~0u)
552 ERR("Failed to find suitable image memory type.\n");
553 VK_CALL(vkDestroyImage(device_vk
->vk_device
, image
->vk_image
, NULL
));
554 image
->vk_image
= VK_NULL_HANDLE
;
558 image
->memory
= wined3d_context_vk_allocate_memory(context_vk
, memory_type_idx
,
559 memory_requirements
.size
, &image
->vk_memory
);
560 if (!image
->vk_memory
)
562 ERR("Failed to allocate image memory.\n");
563 VK_CALL(vkDestroyImage(device_vk
->vk_device
, image
->vk_image
, NULL
));
564 image
->vk_image
= VK_NULL_HANDLE
;
568 vr
= VK_CALL(vkBindImageMemory(device_vk
->vk_device
, image
->vk_image
, image
->vk_memory
,
569 image
->memory
? image
->memory
->offset
: 0));
570 if (vr
!= VK_SUCCESS
)
572 VK_CALL(vkDestroyImage(device_vk
->vk_device
, image
->vk_image
, NULL
));
574 wined3d_allocator_block_free(image
->memory
);
576 VK_CALL(vkFreeMemory(device_vk
->vk_device
, image
->vk_memory
, NULL
));
577 ERR("Failed to bind image memory, vr %s.\n", wined3d_debug_vkresult(vr
));
578 image
->memory
= NULL
;
579 image
->vk_memory
= VK_NULL_HANDLE
;
580 image
->vk_image
= VK_NULL_HANDLE
;
587 static struct wined3d_retired_object_vk
*wined3d_context_vk_get_retired_object_vk(struct wined3d_context_vk
*context_vk
)
589 struct wined3d_retired_objects_vk
*retired
= &context_vk
->retired
;
590 struct wined3d_retired_object_vk
*o
;
595 retired
->free
= o
->u
.next
;
599 if (!wined3d_array_reserve((void **)&retired
->objects
, &retired
->size
,
600 retired
->count
+ 1, sizeof(*retired
->objects
)))
603 return &retired
->objects
[retired
->count
++];
606 void wined3d_context_vk_destroy_vk_framebuffer(struct wined3d_context_vk
*context_vk
,
607 VkFramebuffer vk_framebuffer
, uint64_t command_buffer_id
)
609 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
610 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
611 struct wined3d_retired_object_vk
*o
;
613 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
615 VK_CALL(vkDestroyFramebuffer(device_vk
->vk_device
, vk_framebuffer
, NULL
));
616 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer
));
620 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
622 ERR("Leaking framebuffer 0x%s.\n", wine_dbgstr_longlong(vk_framebuffer
));
626 o
->type
= WINED3D_RETIRED_FRAMEBUFFER_VK
;
627 o
->u
.vk_framebuffer
= vk_framebuffer
;
628 o
->command_buffer_id
= command_buffer_id
;
631 static void wined3d_context_vk_destroy_vk_descriptor_pool(struct wined3d_context_vk
*context_vk
,
632 VkDescriptorPool vk_descriptor_pool
, uint64_t command_buffer_id
)
634 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
635 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
636 struct wined3d_retired_object_vk
*o
;
638 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
640 VK_CALL(vkDestroyDescriptorPool(device_vk
->vk_device
, vk_descriptor_pool
, NULL
));
641 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool
));
645 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
647 ERR("Leaking descriptor pool 0x%s.\n", wine_dbgstr_longlong(vk_descriptor_pool
));
651 o
->type
= WINED3D_RETIRED_DESCRIPTOR_POOL_VK
;
652 o
->u
.vk_descriptor_pool
= vk_descriptor_pool
;
653 o
->command_buffer_id
= command_buffer_id
;
656 void wined3d_context_vk_destroy_vk_memory(struct wined3d_context_vk
*context_vk
,
657 VkDeviceMemory vk_memory
, uint64_t command_buffer_id
)
659 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
660 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
661 struct wined3d_retired_object_vk
*o
;
663 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
665 VK_CALL(vkFreeMemory(device_vk
->vk_device
, vk_memory
, NULL
));
666 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(vk_memory
));
670 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
672 ERR("Leaking memory 0x%s.\n", wine_dbgstr_longlong(vk_memory
));
676 o
->type
= WINED3D_RETIRED_MEMORY_VK
;
677 o
->u
.vk_memory
= vk_memory
;
678 o
->command_buffer_id
= command_buffer_id
;
681 void wined3d_context_vk_destroy_allocator_block(struct wined3d_context_vk
*context_vk
,
682 struct wined3d_allocator_block
*block
, uint64_t command_buffer_id
)
684 struct wined3d_retired_object_vk
*o
;
686 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
688 wined3d_allocator_block_free(block
);
689 TRACE("Freed block %p.\n", block
);
693 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
695 ERR("Leaking block %p.\n", block
);
699 o
->type
= WINED3D_RETIRED_ALLOCATOR_BLOCK_VK
;
701 o
->command_buffer_id
= command_buffer_id
;
704 static void wined3d_bo_slab_vk_free_slice(struct wined3d_bo_slab_vk
*slab
,
705 SIZE_T idx
, struct wined3d_context_vk
*context_vk
)
707 struct wined3d_bo_slab_vk_key key
;
708 struct wine_rb_entry
*entry
;
710 TRACE("slab %p, idx %lu, context_vk %p.\n", slab
, idx
, context_vk
);
714 key
.memory_type
= slab
->requested_memory_type
;
715 key
.usage
= slab
->bo
.usage
;
716 key
.size
= slab
->bo
.size
;
718 if ((entry
= wine_rb_get(&context_vk
->bo_slab_available
, &key
)))
720 slab
->next
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_bo_slab_vk
, entry
);
721 wine_rb_replace(&context_vk
->bo_slab_available
, entry
, &slab
->entry
);
723 else if (wine_rb_put(&context_vk
->bo_slab_available
, &key
, &slab
->entry
) < 0)
725 ERR("Unable to return slab %p (map 0x%08x) to available tree.\n", slab
, slab
->map
);
728 slab
->map
|= 1u << idx
;
731 static void wined3d_context_vk_destroy_bo_slab_slice(struct wined3d_context_vk
*context_vk
,
732 struct wined3d_bo_slab_vk
*slab
, SIZE_T idx
, uint64_t command_buffer_id
)
734 struct wined3d_retired_object_vk
*o
;
736 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
738 wined3d_bo_slab_vk_free_slice(slab
, idx
, context_vk
);
742 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
744 ERR("Leaking slab %p, slice %#lx.\n", slab
, idx
);
748 o
->type
= WINED3D_RETIRED_BO_SLAB_SLICE_VK
;
749 o
->u
.slice
.slab
= slab
;
750 o
->u
.slice
.idx
= idx
;
751 o
->command_buffer_id
= command_buffer_id
;
754 static void wined3d_context_vk_destroy_vk_buffer(struct wined3d_context_vk
*context_vk
,
755 VkBuffer vk_buffer
, uint64_t command_buffer_id
)
757 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
758 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
759 struct wined3d_retired_object_vk
*o
;
761 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
763 VK_CALL(vkDestroyBuffer(device_vk
->vk_device
, vk_buffer
, NULL
));
764 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer
));
768 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
770 ERR("Leaking buffer 0x%s.\n", wine_dbgstr_longlong(vk_buffer
));
774 o
->type
= WINED3D_RETIRED_BUFFER_VK
;
775 o
->u
.vk_buffer
= vk_buffer
;
776 o
->command_buffer_id
= command_buffer_id
;
779 void wined3d_context_vk_destroy_vk_image(struct wined3d_context_vk
*context_vk
,
780 VkImage vk_image
, uint64_t command_buffer_id
)
782 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
783 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
784 struct wined3d_retired_object_vk
*o
;
786 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
788 VK_CALL(vkDestroyImage(device_vk
->vk_device
, vk_image
, NULL
));
789 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(vk_image
));
793 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
795 ERR("Leaking image 0x%s.\n", wine_dbgstr_longlong(vk_image
));
799 o
->type
= WINED3D_RETIRED_IMAGE_VK
;
800 o
->u
.vk_image
= vk_image
;
801 o
->command_buffer_id
= command_buffer_id
;
804 void wined3d_context_vk_destroy_vk_buffer_view(struct wined3d_context_vk
*context_vk
,
805 VkBufferView vk_view
, uint64_t command_buffer_id
)
807 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
808 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
809 struct wined3d_retired_object_vk
*o
;
811 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
813 VK_CALL(vkDestroyBufferView(device_vk
->vk_device
, vk_view
, NULL
));
814 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view
));
818 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
820 ERR("Leaking buffer view 0x%s.\n", wine_dbgstr_longlong(vk_view
));
824 o
->type
= WINED3D_RETIRED_BUFFER_VIEW_VK
;
825 o
->u
.vk_buffer_view
= vk_view
;
826 o
->command_buffer_id
= command_buffer_id
;
829 void wined3d_context_vk_destroy_vk_image_view(struct wined3d_context_vk
*context_vk
,
830 VkImageView vk_view
, uint64_t command_buffer_id
)
832 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
833 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
834 struct wined3d_retired_object_vk
*o
;
836 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
838 VK_CALL(vkDestroyImageView(device_vk
->vk_device
, vk_view
, NULL
));
839 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(vk_view
));
843 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
845 ERR("Leaking image view 0x%s.\n", wine_dbgstr_longlong(vk_view
));
849 o
->type
= WINED3D_RETIRED_IMAGE_VIEW_VK
;
850 o
->u
.vk_image_view
= vk_view
;
851 o
->command_buffer_id
= command_buffer_id
;
854 void wined3d_context_vk_destroy_vk_sampler(struct wined3d_context_vk
*context_vk
,
855 VkSampler vk_sampler
, uint64_t command_buffer_id
)
857 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
858 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
859 struct wined3d_retired_object_vk
*o
;
861 if (context_vk
->completed_command_buffer_id
> command_buffer_id
)
863 VK_CALL(vkDestroySampler(device_vk
->vk_device
, vk_sampler
, NULL
));
864 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler
));
868 if (!(o
= wined3d_context_vk_get_retired_object_vk(context_vk
)))
870 ERR("Leaking sampler 0x%s.\n", wine_dbgstr_longlong(vk_sampler
));
874 o
->type
= WINED3D_RETIRED_SAMPLER_VK
;
875 o
->u
.vk_sampler
= vk_sampler
;
876 o
->command_buffer_id
= command_buffer_id
;
879 void wined3d_context_vk_destroy_image(struct wined3d_context_vk
*context_vk
, struct wined3d_image_vk
*image
)
881 wined3d_context_vk_destroy_vk_image(context_vk
, image
->vk_image
, image
->command_buffer_id
);
883 wined3d_context_vk_destroy_allocator_block(context_vk
, image
->memory
,
884 image
->command_buffer_id
);
886 wined3d_context_vk_destroy_vk_memory(context_vk
, image
->vk_memory
, image
->command_buffer_id
);
888 image
->vk_image
= VK_NULL_HANDLE
;
889 image
->vk_memory
= VK_NULL_HANDLE
;
890 image
->memory
= NULL
;
893 void wined3d_context_vk_destroy_bo(struct wined3d_context_vk
*context_vk
, const struct wined3d_bo_vk
*bo
)
895 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
896 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
897 struct wined3d_bo_slab_vk
*slab_vk
;
898 size_t object_size
, idx
;
900 TRACE("context_vk %p, bo %p.\n", context_vk
, bo
);
902 if ((slab_vk
= bo
->slab
))
905 wined3d_bo_slab_vk_unmap(slab_vk
, context_vk
);
906 object_size
= slab_vk
->bo
.size
/ 32;
907 idx
= bo
->buffer_offset
/ object_size
;
908 wined3d_context_vk_destroy_bo_slab_slice(context_vk
, slab_vk
, idx
, bo
->command_buffer_id
);
912 wined3d_context_vk_destroy_vk_buffer(context_vk
, bo
->vk_buffer
, bo
->command_buffer_id
);
916 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo
->memory
->chunk
), context_vk
);
917 wined3d_context_vk_destroy_allocator_block(context_vk
, bo
->memory
, bo
->command_buffer_id
);
922 VK_CALL(vkUnmapMemory(device_vk
->vk_device
, bo
->vk_memory
));
923 wined3d_context_vk_destroy_vk_memory(context_vk
, bo
->vk_memory
, bo
->command_buffer_id
);
925 if (bo
->command_buffer_id
== context_vk
->current_command_buffer
.id
)
926 context_vk
->retired_bo_size
+= bo
->size
;
929 void wined3d_context_vk_poll_command_buffers(struct wined3d_context_vk
*context_vk
)
931 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
932 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
933 struct wined3d_command_buffer_vk
*buffer
;
936 while (i
< context_vk
->submitted
.buffer_count
)
938 buffer
= &context_vk
->submitted
.buffers
[i
];
939 if (VK_CALL(vkGetFenceStatus(device_vk
->vk_device
, buffer
->vk_fence
)) == VK_NOT_READY
)
945 TRACE("Command buffer %p with id 0x%s has finished.\n",
946 buffer
->vk_command_buffer
, wine_dbgstr_longlong(buffer
->id
));
947 VK_CALL(vkDestroyFence(device_vk
->vk_device
, buffer
->vk_fence
, NULL
));
948 VK_CALL(vkFreeCommandBuffers(device_vk
->vk_device
,
949 context_vk
->vk_command_pool
, 1, &buffer
->vk_command_buffer
));
951 if (buffer
->id
> context_vk
->completed_command_buffer_id
)
952 context_vk
->completed_command_buffer_id
= buffer
->id
;
953 *buffer
= context_vk
->submitted
.buffers
[--context_vk
->submitted
.buffer_count
];
957 static void wined3d_context_vk_cleanup_resources(struct wined3d_context_vk
*context_vk
)
959 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
960 struct wined3d_retired_objects_vk
*retired
= &context_vk
->retired
;
961 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
962 struct wined3d_retired_object_vk
*o
;
963 uint64_t command_buffer_id
;
966 wined3d_context_vk_poll_command_buffers(context_vk
);
967 command_buffer_id
= context_vk
->completed_command_buffer_id
;
969 retired
->free
= NULL
;
970 for (i
= retired
->count
; i
; --i
)
972 o
= &retired
->objects
[i
- 1];
974 if (o
->type
!= WINED3D_RETIRED_FREE_VK
&& o
->command_buffer_id
> command_buffer_id
)
979 case WINED3D_RETIRED_FREE_VK
:
983 case WINED3D_RETIRED_FRAMEBUFFER_VK
:
984 VK_CALL(vkDestroyFramebuffer(device_vk
->vk_device
, o
->u
.vk_framebuffer
, NULL
));
985 TRACE("Destroyed framebuffer 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_framebuffer
));
988 case WINED3D_RETIRED_DESCRIPTOR_POOL_VK
:
989 VK_CALL(vkDestroyDescriptorPool(device_vk
->vk_device
, o
->u
.vk_descriptor_pool
, NULL
));
990 TRACE("Destroyed descriptor pool 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_descriptor_pool
));
993 case WINED3D_RETIRED_MEMORY_VK
:
994 VK_CALL(vkFreeMemory(device_vk
->vk_device
, o
->u
.vk_memory
, NULL
));
995 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_memory
));
998 case WINED3D_RETIRED_ALLOCATOR_BLOCK_VK
:
999 TRACE("Destroying block %p.\n", o
->u
.block
);
1000 wined3d_allocator_block_free(o
->u
.block
);
1003 case WINED3D_RETIRED_BO_SLAB_SLICE_VK
:
1004 wined3d_bo_slab_vk_free_slice(o
->u
.slice
.slab
, o
->u
.slice
.idx
, context_vk
);
1007 case WINED3D_RETIRED_BUFFER_VK
:
1008 VK_CALL(vkDestroyBuffer(device_vk
->vk_device
, o
->u
.vk_buffer
, NULL
));
1009 TRACE("Destroyed buffer 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_buffer
));
1012 case WINED3D_RETIRED_IMAGE_VK
:
1013 VK_CALL(vkDestroyImage(device_vk
->vk_device
, o
->u
.vk_image
, NULL
));
1014 TRACE("Destroyed image 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_image
));
1017 case WINED3D_RETIRED_BUFFER_VIEW_VK
:
1018 VK_CALL(vkDestroyBufferView(device_vk
->vk_device
, o
->u
.vk_buffer_view
, NULL
));
1019 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_buffer_view
));
1022 case WINED3D_RETIRED_IMAGE_VIEW_VK
:
1023 VK_CALL(vkDestroyImageView(device_vk
->vk_device
, o
->u
.vk_image_view
, NULL
));
1024 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_image_view
));
1027 case WINED3D_RETIRED_SAMPLER_VK
:
1028 VK_CALL(vkDestroySampler(device_vk
->vk_device
, o
->u
.vk_sampler
, NULL
));
1029 TRACE("Destroyed sampler 0x%s.\n", wine_dbgstr_longlong(o
->u
.vk_sampler
));
1033 ERR("Unhandled object type %#x.\n", o
->type
);
1037 if (i
== retired
->count
)
1043 o
->type
= WINED3D_RETIRED_FREE_VK
;
1044 o
->u
.next
= retired
->free
;
1049 static void wined3d_context_vk_destroy_bo_slab(struct wine_rb_entry
*entry
, void *ctx
)
1051 struct wined3d_context_vk
*context_vk
= ctx
;
1052 struct wined3d_bo_slab_vk
*slab
, *next
;
1054 slab
= WINE_RB_ENTRY_VALUE(entry
, struct wined3d_bo_slab_vk
, entry
);
1058 wined3d_context_vk_destroy_bo(context_vk
, &slab
->bo
);
1064 static void wined3d_context_vk_destroy_graphics_pipeline(struct wine_rb_entry
*entry
, void *ctx
)
1066 struct wined3d_graphics_pipeline_vk
*pipeline_vk
= WINE_RB_ENTRY_VALUE(entry
,
1067 struct wined3d_graphics_pipeline_vk
, entry
);
1068 struct wined3d_context_vk
*context_vk
= ctx
;
1069 const struct wined3d_vk_info
*vk_info
;
1070 struct wined3d_device_vk
*device_vk
;
1072 vk_info
= context_vk
->vk_info
;
1073 device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1075 VK_CALL(vkDestroyPipeline(device_vk
->vk_device
, pipeline_vk
->vk_pipeline
, NULL
));
1076 heap_free(pipeline_vk
);
1079 static void wined3d_context_vk_destroy_pipeline_layout(struct wine_rb_entry
*entry
, void *ctx
)
1081 struct wined3d_pipeline_layout_vk
*layout
= WINE_RB_ENTRY_VALUE(entry
,
1082 struct wined3d_pipeline_layout_vk
, entry
);
1083 struct wined3d_context_vk
*context_vk
= ctx
;
1084 const struct wined3d_vk_info
*vk_info
;
1085 struct wined3d_device_vk
*device_vk
;
1087 vk_info
= context_vk
->vk_info
;
1088 device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1090 VK_CALL(vkDestroyPipelineLayout(device_vk
->vk_device
, layout
->vk_pipeline_layout
, NULL
));
1091 VK_CALL(vkDestroyDescriptorSetLayout(device_vk
->vk_device
, layout
->vk_set_layout
, NULL
));
1092 heap_free(layout
->key
.bindings
);
1096 static void wined3d_render_pass_key_vk_init(struct wined3d_render_pass_key_vk
*key
,
1097 const struct wined3d_fb_state
*fb
, unsigned int rt_count
, bool depth_stencil
, uint32_t clear_flags
)
1099 struct wined3d_render_pass_attachment_vk
*a
;
1100 struct wined3d_rendertarget_view
*view
;
1103 memset(key
, 0, sizeof(*key
));
1105 for (i
= 0; i
< rt_count
; ++i
)
1107 if (!(view
= fb
->render_targets
[i
]) || view
->format
->id
== WINED3DFMT_NULL
)
1111 a
->vk_format
= wined3d_format_vk(view
->format
)->vk_format
;
1112 a
->vk_samples
= max(1, wined3d_resource_get_sample_count(view
->resource
));
1113 a
->vk_layout
= wined3d_texture_vk(wined3d_texture_from_resource(view
->resource
))->layout
;
1114 key
->rt_mask
|= 1u << i
;
1117 if (depth_stencil
&& (view
= fb
->depth_stencil
))
1120 a
->vk_format
= wined3d_format_vk(view
->format
)->vk_format
;
1121 a
->vk_samples
= max(1, wined3d_resource_get_sample_count(view
->resource
));
1122 a
->vk_layout
= wined3d_texture_vk(wined3d_texture_from_resource(view
->resource
))->layout
;
1123 key
->rt_mask
|= 1u << WINED3D_MAX_RENDER_TARGETS
;
1126 key
->clear_flags
= clear_flags
;
1129 static void wined3d_render_pass_vk_cleanup(struct wined3d_render_pass_vk
*pass
,
1130 struct wined3d_context_vk
*context_vk
)
1132 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1133 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1135 VK_CALL(vkDestroyRenderPass(device_vk
->vk_device
, pass
->vk_render_pass
, NULL
));
1138 static bool wined3d_render_pass_vk_init(struct wined3d_render_pass_vk
*pass
,
1139 struct wined3d_context_vk
*context_vk
, const struct wined3d_render_pass_key_vk
*key
)
1141 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1142 VkAttachmentReference attachment_references
[WINED3D_MAX_RENDER_TARGETS
];
1143 VkAttachmentDescription attachments
[WINED3D_MAX_RENDER_TARGETS
+ 1];
1144 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1145 const struct wined3d_render_pass_attachment_vk
*a
;
1146 VkAttachmentReference ds_attachment_reference
;
1147 VkAttachmentReference
*ds_reference
= NULL
;
1148 unsigned int attachment_count
, rt_count
, i
;
1149 VkAttachmentDescription
*attachment
;
1150 VkSubpassDescription sub_pass_desc
;
1151 VkRenderPassCreateInfo pass_desc
;
1156 attachment_count
= 0;
1157 mask
= key
->rt_mask
& ((1u << WINED3D_MAX_RENDER_TARGETS
) - 1);
1160 i
= wined3d_bit_scan(&mask
);
1163 attachment
= &attachments
[attachment_count
];
1164 attachment
->flags
= 0;
1165 attachment
->format
= a
->vk_format
;
1166 attachment
->samples
= a
->vk_samples
;
1167 if (key
->clear_flags
& WINED3DCLEAR_TARGET
)
1168 attachment
->loadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
1170 attachment
->loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
1171 attachment
->storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
1172 attachment
->stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_DONT_CARE
;
1173 attachment
->stencilStoreOp
= VK_ATTACHMENT_STORE_OP_DONT_CARE
;
1174 attachment
->initialLayout
= a
->vk_layout
;
1175 attachment
->finalLayout
= a
->vk_layout
;
1177 attachment_references
[i
].attachment
= attachment_count
;
1178 attachment_references
[i
].layout
= a
->vk_layout
;
1184 mask
= ~key
->rt_mask
& ((1u << rt_count
) - 1);
1187 i
= wined3d_bit_scan(&mask
);
1188 attachment_references
[i
].attachment
= VK_ATTACHMENT_UNUSED
;
1189 attachment_references
[i
].layout
= VK_IMAGE_LAYOUT_UNDEFINED
;
1192 if (key
->rt_mask
& (1u << WINED3D_MAX_RENDER_TARGETS
))
1196 attachment
= &attachments
[attachment_count
];
1197 attachment
->flags
= 0;
1198 attachment
->format
= a
->vk_format
;
1199 attachment
->samples
= a
->vk_samples
;
1200 if (key
->clear_flags
& WINED3DCLEAR_ZBUFFER
)
1201 attachment
->loadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
1203 attachment
->loadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
1204 attachment
->storeOp
= VK_ATTACHMENT_STORE_OP_STORE
;
1205 if (key
->clear_flags
& WINED3DCLEAR_STENCIL
)
1206 attachment
->stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_CLEAR
;
1208 attachment
->stencilLoadOp
= VK_ATTACHMENT_LOAD_OP_LOAD
;
1209 attachment
->stencilStoreOp
= VK_ATTACHMENT_STORE_OP_STORE
;
1210 attachment
->initialLayout
= a
->vk_layout
;
1211 attachment
->finalLayout
= a
->vk_layout
;
1213 ds_reference
= &ds_attachment_reference
;
1214 ds_reference
->attachment
= attachment_count
;
1215 ds_reference
->layout
= a
->vk_layout
;
1220 sub_pass_desc
.flags
= 0;
1221 sub_pass_desc
.pipelineBindPoint
= VK_PIPELINE_BIND_POINT_GRAPHICS
;
1222 sub_pass_desc
.inputAttachmentCount
= 0;
1223 sub_pass_desc
.pInputAttachments
= NULL
;
1224 sub_pass_desc
.colorAttachmentCount
= rt_count
;
1225 sub_pass_desc
.pColorAttachments
= attachment_references
;
1226 sub_pass_desc
.pResolveAttachments
= NULL
;
1227 sub_pass_desc
.pDepthStencilAttachment
= ds_reference
;
1228 sub_pass_desc
.preserveAttachmentCount
= 0;
1229 sub_pass_desc
.pPreserveAttachments
= NULL
;
1231 pass_desc
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO
;
1232 pass_desc
.pNext
= NULL
;
1233 pass_desc
.flags
= 0;
1234 pass_desc
.attachmentCount
= attachment_count
;
1235 pass_desc
.pAttachments
= attachments
;
1236 pass_desc
.subpassCount
= 1;
1237 pass_desc
.pSubpasses
= &sub_pass_desc
;
1238 pass_desc
.dependencyCount
= 0;
1239 pass_desc
.pDependencies
= NULL
;
1242 if ((vr
= VK_CALL(vkCreateRenderPass(device_vk
->vk_device
,
1243 &pass_desc
, NULL
, &pass
->vk_render_pass
))) < 0)
1245 WARN("Failed to create Vulkan render pass, vr %d.\n", vr
);
1252 VkRenderPass
wined3d_context_vk_get_render_pass(struct wined3d_context_vk
*context_vk
,
1253 const struct wined3d_fb_state
*fb
, unsigned int rt_count
, bool depth_stencil
, uint32_t clear_flags
)
1255 struct wined3d_render_pass_key_vk key
;
1256 struct wined3d_render_pass_vk
*pass
;
1257 struct wine_rb_entry
*entry
;
1259 wined3d_render_pass_key_vk_init(&key
, fb
, rt_count
, depth_stencil
, clear_flags
);
1260 if ((entry
= wine_rb_get(&context_vk
->render_passes
, &key
)))
1261 return WINE_RB_ENTRY_VALUE(entry
, struct wined3d_render_pass_vk
, entry
)->vk_render_pass
;
1263 if (!(pass
= heap_alloc(sizeof(*pass
))))
1264 return VK_NULL_HANDLE
;
1266 if (!wined3d_render_pass_vk_init(pass
, context_vk
, &key
))
1269 return VK_NULL_HANDLE
;
1272 if (wine_rb_put(&context_vk
->render_passes
, &pass
->key
, &pass
->entry
) == -1)
1274 ERR("Failed to insert render pass.\n");
1275 wined3d_render_pass_vk_cleanup(pass
, context_vk
);
1277 return VK_NULL_HANDLE
;
1280 return pass
->vk_render_pass
;
1283 void wined3d_context_vk_end_current_render_pass(struct wined3d_context_vk
*context_vk
)
1285 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1286 VkCommandBuffer vk_command_buffer
;
1288 if (context_vk
->vk_render_pass
)
1290 vk_command_buffer
= context_vk
->current_command_buffer
.vk_command_buffer
;
1291 VK_CALL(vkCmdEndRenderPass(vk_command_buffer
));
1292 context_vk
->vk_render_pass
= VK_NULL_HANDLE
;
1293 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
,
1294 VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
, 0, 0, NULL
, 0, NULL
, 0, NULL
));
1297 if (context_vk
->vk_framebuffer
)
1299 wined3d_context_vk_destroy_vk_framebuffer(context_vk
,
1300 context_vk
->vk_framebuffer
, context_vk
->current_command_buffer
.id
);
1301 context_vk
->vk_framebuffer
= VK_NULL_HANDLE
;
1305 static void wined3d_context_vk_destroy_render_pass(struct wine_rb_entry
*entry
, void *ctx
)
1307 struct wined3d_render_pass_vk
*pass
= WINE_RB_ENTRY_VALUE(entry
,
1308 struct wined3d_render_pass_vk
, entry
);
1310 wined3d_render_pass_vk_cleanup(pass
, ctx
);
1314 static void wined3d_shader_descriptor_writes_vk_cleanup(struct wined3d_shader_descriptor_writes_vk
*writes
)
1316 heap_free(writes
->writes
);
1319 static void wined3d_context_vk_destroy_query_pools(struct wined3d_context_vk
*context_vk
, struct list
*free_pools
)
1321 struct wined3d_query_pool_vk
*pool_vk
, *entry
;
1323 LIST_FOR_EACH_ENTRY_SAFE(pool_vk
, entry
, free_pools
, struct wined3d_query_pool_vk
, entry
)
1325 wined3d_query_pool_vk_cleanup(pool_vk
, context_vk
);
1330 bool wined3d_context_vk_allocate_query(struct wined3d_context_vk
*context_vk
,
1331 enum wined3d_query_type type
, struct wined3d_query_pool_idx_vk
*pool_idx
)
1333 struct wined3d_query_pool_vk
*pool_vk
, *entry
;
1334 struct list
*free_pools
;
1339 case WINED3D_QUERY_TYPE_OCCLUSION
:
1340 free_pools
= &context_vk
->free_occlusion_query_pools
;
1343 case WINED3D_QUERY_TYPE_TIMESTAMP
:
1344 free_pools
= &context_vk
->free_timestamp_query_pools
;
1347 case WINED3D_QUERY_TYPE_PIPELINE_STATISTICS
:
1348 free_pools
= &context_vk
->free_pipeline_statistics_query_pools
;
1351 case WINED3D_QUERY_TYPE_SO_STATISTICS
:
1352 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM0
:
1353 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM1
:
1354 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM2
:
1355 case WINED3D_QUERY_TYPE_SO_STATISTICS_STREAM3
:
1356 free_pools
= &context_vk
->free_stream_output_statistics_query_pools
;
1360 FIXME("Unhandled query type %#x.\n", type
);
1364 LIST_FOR_EACH_ENTRY_SAFE(pool_vk
, entry
, free_pools
, struct wined3d_query_pool_vk
, entry
)
1366 if (wined3d_query_pool_vk_allocate_query(pool_vk
, &idx
))
1368 list_remove(&pool_vk
->entry
);
1371 if (!(pool_vk
= heap_alloc_zero(sizeof(*pool_vk
))))
1373 if (!wined3d_query_pool_vk_init(pool_vk
, context_vk
, type
, free_pools
))
1379 if (!wined3d_query_pool_vk_allocate_query(pool_vk
, &idx
))
1381 wined3d_query_pool_vk_cleanup(pool_vk
, context_vk
);
1387 pool_idx
->pool_vk
= pool_vk
;
1388 pool_idx
->idx
= idx
;
1393 void wined3d_context_vk_cleanup(struct wined3d_context_vk
*context_vk
)
1395 struct wined3d_command_buffer_vk
*buffer
= &context_vk
->current_command_buffer
;
1396 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1397 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1399 if (buffer
->vk_command_buffer
)
1401 VK_CALL(vkFreeCommandBuffers(device_vk
->vk_device
,
1402 context_vk
->vk_command_pool
, 1, &buffer
->vk_command_buffer
));
1403 buffer
->vk_command_buffer
= VK_NULL_HANDLE
;
1406 wined3d_context_vk_wait_command_buffer(context_vk
, buffer
->id
- 1);
1407 context_vk
->completed_command_buffer_id
= buffer
->id
;
1409 heap_free(context_vk
->compute
.bindings
.bindings
);
1410 heap_free(context_vk
->graphics
.bindings
.bindings
);
1411 if (context_vk
->vk_descriptor_pool
)
1412 VK_CALL(vkDestroyDescriptorPool(device_vk
->vk_device
, context_vk
->vk_descriptor_pool
, NULL
));
1413 if (context_vk
->vk_framebuffer
)
1414 VK_CALL(vkDestroyFramebuffer(device_vk
->vk_device
, context_vk
->vk_framebuffer
, NULL
));
1415 VK_CALL(vkDestroyCommandPool(device_vk
->vk_device
, context_vk
->vk_command_pool
, NULL
));
1416 if (context_vk
->vk_so_counter_bo
.vk_buffer
)
1417 wined3d_context_vk_destroy_bo(context_vk
, &context_vk
->vk_so_counter_bo
);
1418 wined3d_context_vk_cleanup_resources(context_vk
);
1419 wined3d_context_vk_destroy_query_pools(context_vk
, &context_vk
->free_occlusion_query_pools
);
1420 wined3d_context_vk_destroy_query_pools(context_vk
, &context_vk
->free_timestamp_query_pools
);
1421 wined3d_context_vk_destroy_query_pools(context_vk
, &context_vk
->free_pipeline_statistics_query_pools
);
1422 wined3d_context_vk_destroy_query_pools(context_vk
, &context_vk
->free_stream_output_statistics_query_pools
);
1423 wine_rb_destroy(&context_vk
->bo_slab_available
, wined3d_context_vk_destroy_bo_slab
, context_vk
);
1424 heap_free(context_vk
->pending_queries
.queries
);
1425 heap_free(context_vk
->submitted
.buffers
);
1426 heap_free(context_vk
->retired
.objects
);
1428 wined3d_shader_descriptor_writes_vk_cleanup(&context_vk
->descriptor_writes
);
1429 wine_rb_destroy(&context_vk
->graphics_pipelines
, wined3d_context_vk_destroy_graphics_pipeline
, context_vk
);
1430 wine_rb_destroy(&context_vk
->pipeline_layouts
, wined3d_context_vk_destroy_pipeline_layout
, context_vk
);
1431 wine_rb_destroy(&context_vk
->render_passes
, wined3d_context_vk_destroy_render_pass
, context_vk
);
1433 wined3d_context_cleanup(&context_vk
->c
);
1436 void wined3d_context_vk_remove_pending_queries(struct wined3d_context_vk
*context_vk
,
1437 struct wined3d_query_vk
*query_vk
)
1439 struct wined3d_pending_queries_vk
*pending
= &context_vk
->pending_queries
;
1440 struct wined3d_pending_query_vk
*p
;
1443 pending
->free_idx
= ~(size_t)0;
1444 for (i
= pending
->count
; i
; --i
)
1446 p
= &pending
->queries
[i
- 1];
1450 if (p
->query_vk
!= query_vk
&& !wined3d_query_vk_accumulate_data(p
->query_vk
, context_vk
, &p
->pool_idx
))
1452 wined3d_query_pool_vk_free_query(p
->pool_idx
.pool_vk
, p
->pool_idx
.idx
);
1453 --p
->query_vk
->pending_count
;
1456 if (i
== pending
->count
)
1463 p
->pool_idx
.pool_vk
= NULL
;
1464 p
->pool_idx
.idx
= pending
->free_idx
;
1465 pending
->free_idx
= i
- 1;
1469 void wined3d_context_vk_accumulate_pending_queries(struct wined3d_context_vk
*context_vk
)
1471 wined3d_context_vk_remove_pending_queries(context_vk
, NULL
);
1474 void wined3d_context_vk_add_pending_query(struct wined3d_context_vk
*context_vk
, struct wined3d_query_vk
*query_vk
)
1476 struct wined3d_pending_queries_vk
*pending
= &context_vk
->pending_queries
;
1477 struct wined3d_pending_query_vk
*p
;
1479 if (pending
->free_idx
!= ~(size_t)0)
1481 p
= &pending
->queries
[pending
->free_idx
];
1482 pending
->free_idx
= p
->pool_idx
.idx
;
1486 if (!wined3d_array_reserve((void **)&pending
->queries
, &pending
->size
,
1487 pending
->count
+ 1, sizeof(*pending
->queries
)))
1489 ERR("Failed to allocate entry.\n");
1492 p
= &pending
->queries
[pending
->count
++];
1495 p
->query_vk
= query_vk
;
1496 p
->pool_idx
= query_vk
->pool_idx
;
1497 ++query_vk
->pending_count
;
1500 VkCommandBuffer
wined3d_context_vk_get_command_buffer(struct wined3d_context_vk
*context_vk
)
1502 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1503 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1504 VkCommandBufferAllocateInfo command_buffer_info
;
1505 struct wined3d_command_buffer_vk
*buffer
;
1506 VkCommandBufferBeginInfo begin_info
;
1507 struct wined3d_query_vk
*query_vk
;
1510 TRACE("context_vk %p.\n", context_vk
);
1512 buffer
= &context_vk
->current_command_buffer
;
1513 if (buffer
->vk_command_buffer
)
1515 if (context_vk
->retired_bo_size
> WINED3D_RETIRED_BO_SIZE_THRESHOLD
)
1516 wined3d_context_vk_submit_command_buffer(context_vk
, 0, NULL
, NULL
, 0, NULL
);
1519 TRACE("Returning existing command buffer %p with id 0x%s.\n",
1520 buffer
->vk_command_buffer
, wine_dbgstr_longlong(buffer
->id
));
1521 return buffer
->vk_command_buffer
;
1525 command_buffer_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
;
1526 command_buffer_info
.pNext
= NULL
;
1527 command_buffer_info
.commandPool
= context_vk
->vk_command_pool
;
1528 command_buffer_info
.level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
;
1529 command_buffer_info
.commandBufferCount
= 1;
1530 if ((vr
= VK_CALL(vkAllocateCommandBuffers(device_vk
->vk_device
,
1531 &command_buffer_info
, &buffer
->vk_command_buffer
))) < 0)
1533 WARN("Failed to allocate Vulkan command buffer, vr %s.\n", wined3d_debug_vkresult(vr
));
1534 return VK_NULL_HANDLE
;
1537 begin_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO
;
1538 begin_info
.pNext
= NULL
;
1539 begin_info
.flags
= 0;
1540 begin_info
.pInheritanceInfo
= NULL
;
1541 if ((vr
= VK_CALL(vkBeginCommandBuffer(buffer
->vk_command_buffer
, &begin_info
))) < 0)
1543 WARN("Failed to begin command buffer, vr %s.\n", wined3d_debug_vkresult(vr
));
1544 VK_CALL(vkFreeCommandBuffers(device_vk
->vk_device
, context_vk
->vk_command_pool
,
1545 1, &buffer
->vk_command_buffer
));
1546 return buffer
->vk_command_buffer
= VK_NULL_HANDLE
;
1549 wined3d_context_vk_accumulate_pending_queries(context_vk
);
1550 LIST_FOR_EACH_ENTRY(query_vk
, &context_vk
->active_queries
, struct wined3d_query_vk
, entry
)
1552 wined3d_query_vk_resume(query_vk
, context_vk
);
1555 TRACE("Created new command buffer %p with id 0x%s.\n",
1556 buffer
->vk_command_buffer
, wine_dbgstr_longlong(buffer
->id
));
1558 return buffer
->vk_command_buffer
;
1561 void wined3d_context_vk_submit_command_buffer(struct wined3d_context_vk
*context_vk
,
1562 unsigned int wait_semaphore_count
, const VkSemaphore
*wait_semaphores
, const VkPipelineStageFlags
*wait_stages
,
1563 unsigned int signal_semaphore_count
, const VkSemaphore
*signal_semaphores
)
1565 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1566 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1567 struct wined3d_command_buffer_vk
*buffer
;
1568 struct wined3d_query_vk
*query_vk
;
1569 VkFenceCreateInfo fence_desc
;
1570 VkSubmitInfo submit_info
;
1573 TRACE("context_vk %p, wait_semaphore_count %u, wait_semaphores %p, wait_stages %p,"
1574 "signal_semaphore_count %u, signal_semaphores %p.\n",
1575 context_vk
, wait_semaphore_count
, wait_semaphores
, wait_stages
,
1576 signal_semaphore_count
, signal_semaphores
);
1578 buffer
= &context_vk
->current_command_buffer
;
1579 if (!buffer
->vk_command_buffer
)
1582 TRACE("Submitting command buffer %p with id 0x%s.\n",
1583 buffer
->vk_command_buffer
, wine_dbgstr_longlong(buffer
->id
));
1585 LIST_FOR_EACH_ENTRY(query_vk
, &context_vk
->active_queries
, struct wined3d_query_vk
, entry
)
1587 wined3d_query_vk_suspend(query_vk
, context_vk
);
1590 wined3d_context_vk_end_current_render_pass(context_vk
);
1591 context_vk
->graphics
.vk_pipeline
= VK_NULL_HANDLE
;
1592 context_vk
->update_compute_pipeline
= 1;
1593 context_vk
->update_stream_output
= 1;
1594 context_vk
->c
.update_shader_resource_bindings
= 1;
1595 context_vk
->c
.update_compute_shader_resource_bindings
= 1;
1596 context_vk
->c
.update_unordered_access_view_bindings
= 1;
1597 context_vk
->c
.update_compute_unordered_access_view_bindings
= 1;
1598 context_invalidate_state(&context_vk
->c
, STATE_STREAMSRC
);
1599 context_invalidate_state(&context_vk
->c
, STATE_INDEXBUFFER
);
1600 context_invalidate_state(&context_vk
->c
, STATE_BLEND_FACTOR
);
1601 context_invalidate_state(&context_vk
->c
, STATE_STENCIL_REF
);
1603 VK_CALL(vkEndCommandBuffer(buffer
->vk_command_buffer
));
1605 fence_desc
.sType
= VK_STRUCTURE_TYPE_FENCE_CREATE_INFO
;
1606 fence_desc
.pNext
= NULL
;
1607 fence_desc
.flags
= 0;
1608 if ((vr
= VK_CALL(vkCreateFence(device_vk
->vk_device
, &fence_desc
, NULL
, &buffer
->vk_fence
))) < 0)
1609 ERR("Failed to create fence, vr %s.\n", wined3d_debug_vkresult(vr
));
1611 submit_info
.sType
= VK_STRUCTURE_TYPE_SUBMIT_INFO
;
1612 submit_info
.pNext
= NULL
;
1613 submit_info
.waitSemaphoreCount
= wait_semaphore_count
;
1614 submit_info
.pWaitSemaphores
= wait_semaphores
;
1615 submit_info
.pWaitDstStageMask
= wait_stages
;
1616 submit_info
.commandBufferCount
= 1;
1617 submit_info
.pCommandBuffers
= &buffer
->vk_command_buffer
;
1618 submit_info
.signalSemaphoreCount
= signal_semaphore_count
;
1619 submit_info
.pSignalSemaphores
= signal_semaphores
;
1621 if ((vr
= VK_CALL(vkQueueSubmit(device_vk
->vk_queue
, 1, &submit_info
, buffer
->vk_fence
))) < 0)
1622 ERR("Failed to submit command buffer %p, vr %s.\n",
1623 buffer
->vk_command_buffer
, wined3d_debug_vkresult(vr
));
1625 if (!wined3d_array_reserve((void **)&context_vk
->submitted
.buffers
, &context_vk
->submitted
.buffers_size
,
1626 context_vk
->submitted
.buffer_count
+ 1, sizeof(*context_vk
->submitted
.buffers
)))
1627 ERR("Failed to grow submitted command buffer array.\n");
1629 context_vk
->submitted
.buffers
[context_vk
->submitted
.buffer_count
++] = *buffer
;
1631 buffer
->vk_command_buffer
= VK_NULL_HANDLE
;
1632 /* We don't expect this to ever happen, but handle it anyway. */
1635 wined3d_context_vk_wait_command_buffer(context_vk
, buffer
->id
- 1);
1636 context_vk
->completed_command_buffer_id
= 0;
1639 context_vk
->retired_bo_size
= 0;
1640 wined3d_context_vk_cleanup_resources(context_vk
);
1643 void wined3d_context_vk_wait_command_buffer(struct wined3d_context_vk
*context_vk
, uint64_t id
)
1645 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
1646 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1649 if (id
<= context_vk
->completed_command_buffer_id
1650 || id
> context_vk
->current_command_buffer
.id
) /* In case the buffer ID wrapped. */
1653 for (i
= 0; i
< context_vk
->submitted
.buffer_count
; ++i
)
1655 if (context_vk
->submitted
.buffers
[i
].id
!= id
)
1658 VK_CALL(vkWaitForFences(device_vk
->vk_device
, 1,
1659 &context_vk
->submitted
.buffers
[i
].vk_fence
, VK_TRUE
, UINT64_MAX
));
1660 wined3d_context_vk_cleanup_resources(context_vk
);
1664 ERR("Failed to find fence for command buffer with id 0x%s.\n", wine_dbgstr_longlong(id
));
1667 void wined3d_context_vk_image_barrier(struct wined3d_context_vk
*context_vk
,
1668 VkCommandBuffer vk_command_buffer
, VkPipelineStageFlags src_stage_mask
, VkPipelineStageFlags dst_stage_mask
,
1669 VkAccessFlags src_access_mask
, VkAccessFlags dst_access_mask
, VkImageLayout old_layout
,
1670 VkImageLayout new_layout
, VkImage image
, const VkImageSubresourceRange
*range
)
1672 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1673 VkImageMemoryBarrier barrier
;
1675 wined3d_context_vk_end_current_render_pass(context_vk
);
1677 barrier
.sType
= VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER
;
1678 barrier
.pNext
= NULL
;
1679 barrier
.srcAccessMask
= src_access_mask
;
1680 barrier
.dstAccessMask
= dst_access_mask
;
1681 barrier
.oldLayout
= old_layout
;
1682 barrier
.newLayout
= new_layout
;
1683 barrier
.srcQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1684 barrier
.dstQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1685 barrier
.image
= image
;
1686 barrier
.subresourceRange
= *range
;
1688 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, src_stage_mask
, dst_stage_mask
, 0, 0, NULL
, 0, NULL
, 1, &barrier
));
1691 static int wined3d_render_pass_vk_compare(const void *key
, const struct wine_rb_entry
*entry
)
1693 const struct wined3d_render_pass_key_vk
*k
= key
;
1694 const struct wined3d_render_pass_vk
*pass
= WINE_RB_ENTRY_VALUE(entry
,
1695 const struct wined3d_render_pass_vk
, entry
);
1697 return memcmp(k
, &pass
->key
, sizeof(*k
));
1700 static int wined3d_pipeline_layout_vk_compare(const void *key
, const struct wine_rb_entry
*entry
)
1702 const struct wined3d_pipeline_layout_key_vk
*a
= key
;
1703 const struct wined3d_pipeline_layout_key_vk
*b
= &WINE_RB_ENTRY_VALUE(entry
,
1704 const struct wined3d_pipeline_layout_vk
, entry
)->key
;
1706 if (a
->binding_count
!= b
->binding_count
)
1707 return a
->binding_count
- b
->binding_count
;
1708 return memcmp(a
->bindings
, b
->bindings
, a
->binding_count
* sizeof(*a
->bindings
));
1711 static int wined3d_graphics_pipeline_vk_compare(const void *key
, const struct wine_rb_entry
*entry
)
1713 const struct wined3d_graphics_pipeline_key_vk
*a
= key
;
1714 const struct wined3d_graphics_pipeline_key_vk
*b
= &WINE_RB_ENTRY_VALUE(entry
,
1715 const struct wined3d_graphics_pipeline_vk
, entry
)->key
;
1719 if (a
->pipeline_desc
.stageCount
!= b
->pipeline_desc
.stageCount
)
1720 return a
->pipeline_desc
.stageCount
- b
->pipeline_desc
.stageCount
;
1721 for (i
= 0; i
< a
->pipeline_desc
.stageCount
; ++i
)
1723 if (a
->stages
[i
].module
!= b
->stages
[i
].module
)
1724 return a
->stages
[i
].module
- b
->stages
[i
].module
;
1727 if (a
->divisor_desc
.vertexBindingDivisorCount
!= b
->divisor_desc
.vertexBindingDivisorCount
)
1728 return a
->divisor_desc
.vertexBindingDivisorCount
- b
->divisor_desc
.vertexBindingDivisorCount
;
1729 if ((ret
= memcmp(a
->divisors
, b
->divisors
,
1730 a
->divisor_desc
.vertexBindingDivisorCount
* sizeof(*a
->divisors
))))
1733 if (a
->input_desc
.vertexAttributeDescriptionCount
!= b
->input_desc
.vertexAttributeDescriptionCount
)
1734 return a
->input_desc
.vertexAttributeDescriptionCount
- b
->input_desc
.vertexAttributeDescriptionCount
;
1735 if ((ret
= memcmp(a
->attributes
, b
->attributes
,
1736 a
->input_desc
.vertexAttributeDescriptionCount
* sizeof(*a
->attributes
))))
1738 if (a
->input_desc
.vertexBindingDescriptionCount
!= b
->input_desc
.vertexBindingDescriptionCount
)
1739 return a
->input_desc
.vertexBindingDescriptionCount
- b
->input_desc
.vertexBindingDescriptionCount
;
1740 if ((ret
= memcmp(a
->bindings
, b
->bindings
,
1741 a
->input_desc
.vertexBindingDescriptionCount
* sizeof(*a
->bindings
))))
1744 if (a
->ia_desc
.topology
!= b
->ia_desc
.topology
)
1745 return a
->ia_desc
.topology
- b
->ia_desc
.topology
;
1746 if (a
->ia_desc
.primitiveRestartEnable
!= b
->ia_desc
.primitiveRestartEnable
)
1747 return a
->ia_desc
.primitiveRestartEnable
- b
->ia_desc
.primitiveRestartEnable
;
1749 if (a
->ts_desc
.patchControlPoints
!= b
->ts_desc
.patchControlPoints
)
1750 return a
->ts_desc
.patchControlPoints
- b
->ts_desc
.patchControlPoints
;
1752 if ((ret
= memcmp(&a
->viewport
, &b
->viewport
, sizeof(a
->viewport
))))
1755 if ((ret
= memcmp(&a
->scissor
, &b
->scissor
, sizeof(a
->scissor
))))
1758 if ((ret
= memcmp(&a
->rs_desc
, &b
->rs_desc
, sizeof(a
->rs_desc
))))
1761 if (a
->ms_desc
.rasterizationSamples
!= b
->ms_desc
.rasterizationSamples
)
1762 return a
->ms_desc
.rasterizationSamples
- b
->ms_desc
.rasterizationSamples
;
1763 if (a
->ms_desc
.alphaToCoverageEnable
!= b
->ms_desc
.alphaToCoverageEnable
)
1764 return a
->ms_desc
.alphaToCoverageEnable
- b
->ms_desc
.alphaToCoverageEnable
;
1765 if (a
->sample_mask
!= b
->sample_mask
)
1766 return a
->sample_mask
- b
->sample_mask
;
1768 if ((ret
= memcmp(&a
->ds_desc
, &b
->ds_desc
, sizeof(a
->ds_desc
))))
1771 if (a
->blend_desc
.attachmentCount
!= b
->blend_desc
.attachmentCount
)
1772 return a
->blend_desc
.attachmentCount
- b
->blend_desc
.attachmentCount
;
1773 if ((ret
= memcmp(a
->blend_attachments
, b
->blend_attachments
,
1774 a
->blend_desc
.attachmentCount
* sizeof(*a
->blend_attachments
))))
1777 if (a
->pipeline_desc
.layout
!= b
->pipeline_desc
.layout
)
1778 return a
->pipeline_desc
.layout
- b
->pipeline_desc
.layout
;
1780 if (a
->pipeline_desc
.renderPass
!= b
->pipeline_desc
.renderPass
)
1781 return a
->pipeline_desc
.renderPass
- b
->pipeline_desc
.renderPass
;
1786 static int wined3d_bo_slab_vk_compare(const void *key
, const struct wine_rb_entry
*entry
)
1788 const struct wined3d_bo_slab_vk
*slab
= WINE_RB_ENTRY_VALUE(entry
, const struct wined3d_bo_slab_vk
, entry
);
1789 const struct wined3d_bo_slab_vk_key
*k
= key
;
1791 if (k
->memory_type
!= slab
->requested_memory_type
)
1792 return k
->memory_type
- slab
->requested_memory_type
;
1793 if (k
->usage
!= slab
->bo
.usage
)
1794 return k
->usage
- slab
->bo
.usage
;
1795 return k
->size
- slab
->bo
.size
;
1798 static void wined3d_context_vk_init_graphics_pipeline_key(struct wined3d_context_vk
*context_vk
)
1800 struct wined3d_graphics_pipeline_key_vk
*key
;
1801 VkPipelineShaderStageCreateInfo
*stage
;
1804 static const VkDynamicState dynamic_states
[] =
1806 VK_DYNAMIC_STATE_BLEND_CONSTANTS
,
1807 VK_DYNAMIC_STATE_STENCIL_REFERENCE
,
1810 key
= &context_vk
->graphics
.pipeline_key_vk
;
1811 memset(key
, 0, sizeof(*key
));
1813 for (i
= 0; i
< ARRAY_SIZE(context_vk
->graphics
.vk_modules
); ++i
)
1815 stage
= &key
->stages
[i
];
1816 stage
->sType
= VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO
;
1817 stage
->pName
= "main";
1820 key
->input_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO
;
1821 key
->input_desc
.pVertexBindingDescriptions
= key
->bindings
;
1822 key
->input_desc
.pVertexAttributeDescriptions
= key
->attributes
;
1824 key
->divisor_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT
;
1825 key
->divisor_desc
.pVertexBindingDivisors
= key
->divisors
;
1827 key
->ia_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO
;
1829 key
->ts_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO
;
1831 key
->vp_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO
;
1832 key
->vp_desc
.viewportCount
= 1;
1833 key
->vp_desc
.pViewports
= &key
->viewport
;
1834 key
->vp_desc
.scissorCount
= 1;
1835 key
->vp_desc
.pScissors
= &key
->scissor
;
1837 key
->rs_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO
;
1838 key
->rs_desc
.lineWidth
= 1.0f
;
1840 key
->ms_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO
;
1841 key
->ms_desc
.pSampleMask
= &key
->sample_mask
;
1843 key
->ds_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO
;
1844 key
->ds_desc
.maxDepthBounds
= 1.0f
;
1846 key
->blend_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO
;
1847 key
->blend_desc
.logicOp
= VK_LOGIC_OP_COPY
;
1848 key
->blend_desc
.pAttachments
= key
->blend_attachments
;
1849 key
->blend_desc
.blendConstants
[0] = 1.0f
;
1850 key
->blend_desc
.blendConstants
[1] = 1.0f
;
1851 key
->blend_desc
.blendConstants
[2] = 1.0f
;
1852 key
->blend_desc
.blendConstants
[3] = 1.0f
;
1854 key
->dynamic_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO
;
1855 key
->dynamic_desc
.dynamicStateCount
= ARRAY_SIZE(dynamic_states
);
1856 key
->dynamic_desc
.pDynamicStates
= dynamic_states
;
1858 key
->pipeline_desc
.sType
= VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO
;
1859 key
->pipeline_desc
.pStages
= key
->stages
;
1860 key
->pipeline_desc
.pVertexInputState
= &key
->input_desc
;
1861 key
->pipeline_desc
.pInputAssemblyState
= &key
->ia_desc
;
1862 key
->pipeline_desc
.pTessellationState
= &key
->ts_desc
;
1863 key
->pipeline_desc
.pViewportState
= &key
->vp_desc
;
1864 key
->pipeline_desc
.pRasterizationState
= &key
->rs_desc
;
1865 key
->pipeline_desc
.pMultisampleState
= &key
->ms_desc
;
1866 key
->pipeline_desc
.pDepthStencilState
= &key
->ds_desc
;
1867 key
->pipeline_desc
.pColorBlendState
= &key
->blend_desc
;
1868 key
->pipeline_desc
.pDynamicState
= &key
->dynamic_desc
;
1869 key
->pipeline_desc
.basePipelineIndex
= -1;
1872 static void wined3d_context_vk_update_rasterisation_state(const struct wined3d_context_vk
*context_vk
,
1873 const struct wined3d_state
*state
, struct wined3d_graphics_pipeline_key_vk
*key
)
1875 const struct wined3d_d3d_info
*d3d_info
= context_vk
->c
.d3d_info
;
1876 VkPipelineRasterizationStateCreateInfo
*desc
= &key
->rs_desc
;
1877 const struct wined3d_rasterizer_state_desc
*r
;
1885 if (!state
->rasterizer_state
)
1887 desc
->depthClampEnable
= VK_FALSE
;
1888 desc
->rasterizerDiscardEnable
= is_rasterization_disabled(state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]);
1889 desc
->cullMode
= VK_CULL_MODE_BACK_BIT
;
1890 desc
->frontFace
= VK_FRONT_FACE_CLOCKWISE
;
1891 desc
->depthBiasEnable
= VK_FALSE
;
1892 desc
->depthBiasConstantFactor
= 0.0f
;
1893 desc
->depthBiasClamp
= 0.0f
;
1894 desc
->depthBiasSlopeFactor
= 0.0f
;
1899 r
= &state
->rasterizer_state
->desc
;
1900 desc
->depthClampEnable
= !r
->depth_clip
;
1901 desc
->rasterizerDiscardEnable
= is_rasterization_disabled(state
->shader
[WINED3D_SHADER_TYPE_GEOMETRY
]);
1902 desc
->cullMode
= vk_cull_mode_from_wined3d(r
->cull_mode
);
1903 desc
->frontFace
= r
->front_ccw
? VK_FRONT_FACE_COUNTER_CLOCKWISE
: VK_FRONT_FACE_CLOCKWISE
;
1905 scale_bias
= r
->scale_bias
;
1906 const_bias
.f32
= r
->depth_bias
;
1907 if (!scale_bias
&& !const_bias
.f32
)
1909 desc
->depthBiasEnable
= VK_FALSE
;
1910 desc
->depthBiasConstantFactor
= 0.0f
;
1911 desc
->depthBiasClamp
= 0.0f
;
1912 desc
->depthBiasSlopeFactor
= 0.0f
;
1917 desc
->depthBiasEnable
= VK_TRUE
;
1918 if (d3d_info
->wined3d_creation_flags
& WINED3D_LEGACY_DEPTH_BIAS
)
1920 const struct wined3d_rendertarget_view
*dsv
;
1922 if ((dsv
= state
->fb
.depth_stencil
))
1924 desc
->depthBiasConstantFactor
= -(float)const_bias
.u32
/ dsv
->format
->depth_bias_scale
;
1925 desc
->depthBiasSlopeFactor
= -(float)const_bias
.u32
;
1929 desc
->depthBiasConstantFactor
= 0.0f
;
1930 desc
->depthBiasSlopeFactor
= 0.0f
;
1935 desc
->depthBiasConstantFactor
= const_bias
.f32
;
1936 desc
->depthBiasSlopeFactor
= scale_bias
;
1938 desc
->depthBiasClamp
= r
->depth_bias_clamp
;
1941 static void wined3d_context_vk_update_blend_state(const struct wined3d_context_vk
*context_vk
,
1942 const struct wined3d_state
*state
, struct wined3d_graphics_pipeline_key_vk
*key
)
1944 VkPipelineColorBlendStateCreateInfo
*desc
= &key
->blend_desc
;
1945 const struct wined3d_blend_state_desc
*b
;
1948 desc
->attachmentCount
= context_vk
->rt_count
;
1950 memset(key
->blend_attachments
, 0, sizeof(key
->blend_attachments
));
1951 if (!state
->blend_state
)
1953 for (i
= 0; i
< context_vk
->rt_count
; ++i
)
1955 key
->blend_attachments
[i
].colorWriteMask
= VK_COLOR_COMPONENT_R_BIT
1956 | VK_COLOR_COMPONENT_G_BIT
1957 | VK_COLOR_COMPONENT_B_BIT
1958 | VK_COLOR_COMPONENT_A_BIT
;
1964 b
= &state
->blend_state
->desc
;
1965 for (i
= 0; i
< context_vk
->rt_count
; ++i
)
1967 const struct wined3d_rendertarget_blend_state_desc
*rt
= &b
->rt
[b
->independent
? i
: 0];
1968 const struct wined3d_rendertarget_view
*rtv
= state
->fb
.render_targets
[i
];
1969 VkPipelineColorBlendAttachmentState
*a
= &key
->blend_attachments
[i
];
1970 enum wined3d_blend src_blend
, dst_blend
;
1971 const struct wined3d_format
*rt_format
;
1973 a
->colorWriteMask
= vk_colour_write_mask_from_wined3d(rt
->writemask
);
1978 rt_format
= rtv
->format
;
1980 rt_format
= wined3d_get_format(context_vk
->c
.device
->adapter
, WINED3DFMT_NULL
, 0);
1981 a
->blendEnable
= VK_TRUE
;
1983 src_blend
= rt
->src
;
1984 dst_blend
= rt
->dst
;
1985 if (src_blend
== WINED3D_BLEND_BOTHSRCALPHA
)
1987 src_blend
= WINED3D_BLEND_SRCALPHA
;
1988 dst_blend
= WINED3D_BLEND_INVSRCALPHA
;
1990 else if (src_blend
== WINED3D_BLEND_BOTHINVSRCALPHA
)
1992 src_blend
= WINED3D_BLEND_INVSRCALPHA
;
1993 dst_blend
= WINED3D_BLEND_SRCALPHA
;
1995 a
->srcColorBlendFactor
= vk_blend_factor_from_wined3d(src_blend
, rt_format
, FALSE
);
1996 a
->dstColorBlendFactor
= vk_blend_factor_from_wined3d(dst_blend
, rt_format
, FALSE
);
1997 a
->colorBlendOp
= vk_blend_op_from_wined3d(rt
->op
);
1999 src_blend
= rt
->src_alpha
;
2000 dst_blend
= rt
->dst_alpha
;
2001 a
->srcAlphaBlendFactor
= vk_blend_factor_from_wined3d(src_blend
, rt_format
, TRUE
);
2002 a
->dstAlphaBlendFactor
= vk_blend_factor_from_wined3d(dst_blend
, rt_format
, TRUE
);
2003 a
->alphaBlendOp
= vk_blend_op_from_wined3d(rt
->op_alpha
);
2007 static VkFormat
vk_format_from_component_type(enum wined3d_component_type component_type
)
2009 switch (component_type
)
2011 case WINED3D_TYPE_UINT
:
2012 return VK_FORMAT_R32G32B32A32_UINT
;
2013 case WINED3D_TYPE_INT
:
2014 return VK_FORMAT_R32G32B32A32_SINT
;
2015 case WINED3D_TYPE_UNKNOWN
:
2016 case WINED3D_TYPE_FLOAT
:
2017 return VK_FORMAT_R32G32B32A32_SFLOAT
;
2019 return VK_FORMAT_UNDEFINED
;
2022 static bool wined3d_context_vk_update_graphics_pipeline_key(struct wined3d_context_vk
*context_vk
,
2023 const struct wined3d_state
*state
, VkPipelineLayout vk_pipeline_layout
, uint32_t *null_buffer_binding
)
2025 unsigned int i
, attribute_count
, binding_count
, divisor_count
, stage_count
;
2026 const struct wined3d_d3d_info
*d3d_info
= context_vk
->c
.d3d_info
;
2027 struct wined3d_graphics_pipeline_key_vk
*key
;
2028 VkPipelineShaderStageCreateInfo
*stage
;
2029 struct wined3d_stream_info stream_info
;
2030 struct wined3d_shader
*vertex_shader
;
2031 VkPrimitiveTopology vk_topology
;
2032 VkShaderModule module
;
2033 bool update
= false;
2036 *null_buffer_binding
= ~0u;
2037 key
= &context_vk
->graphics
.pipeline_key_vk
;
2039 if (context_vk
->c
.shader_update_mask
& ~(1u << WINED3D_SHADER_TYPE_COMPUTE
))
2042 for (i
= 0; i
< ARRAY_SIZE(context_vk
->graphics
.vk_modules
); ++i
)
2044 if (!(module
= context_vk
->graphics
.vk_modules
[i
]))
2047 stage
= &key
->stages
[stage_count
++];
2048 stage
->stage
= vk_shader_stage_from_wined3d(i
);
2049 stage
->module
= module
;
2052 key
->pipeline_desc
.stageCount
= stage_count
;
2057 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_VDECL
)
2058 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_STREAMSRC
)
2059 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX
)))
2061 VkVertexInputAttributeDescription
*a
;
2062 VkVertexInputBindingDescription
*b
;
2064 wined3d_stream_info_from_declaration(&stream_info
, state
, d3d_info
);
2066 for (i
= 0, mask
= 0, attribute_count
= 0, binding_count
= 0; i
< ARRAY_SIZE(stream_info
.elements
); ++i
)
2068 VkVertexInputBindingDivisorDescriptionEXT
*d
;
2069 struct wined3d_stream_info_element
*e
;
2072 if (!(stream_info
.use_map
& (1u << i
)))
2075 a
= &key
->attributes
[attribute_count
++];
2076 e
= &stream_info
.elements
[i
];
2077 binding
= e
->stream_idx
;
2080 a
->binding
= binding
;
2081 a
->format
= wined3d_format_vk(e
->format
)->vk_format
;
2082 a
->offset
= (UINT_PTR
)e
->data
.addr
- state
->streams
[binding
].offset
;
2084 if (mask
& (1u << binding
))
2086 mask
|= 1u << binding
;
2088 b
= &key
->bindings
[binding_count
++];
2089 b
->binding
= binding
;
2090 b
->stride
= e
->stride
;
2091 b
->inputRate
= e
->instanced
? VK_VERTEX_INPUT_RATE_INSTANCE
: VK_VERTEX_INPUT_RATE_VERTEX
;
2095 d
= &key
->divisors
[divisor_count
++];
2096 d
->binding
= binding
;
2097 d
->divisor
= e
->divisor
;
2101 vertex_shader
= state
->shader
[WINED3D_SHADER_TYPE_VERTEX
];
2102 if (vertex_shader
&& (mask
= ~stream_info
.use_map
& vertex_shader
->reg_maps
.input_registers
))
2104 struct wined3d_shader_signature_element
*element
;
2105 struct wined3d_shader_signature
*signature
;
2106 uint32_t null_binding
, location
;
2108 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
2110 if (!state
->streams
[i
].buffer
)
2117 if (i
== ARRAY_SIZE(state
->streams
))
2119 ERR("No streams left for a null buffer binding.\n");
2123 signature
= &vertex_shader
->input_signature
;
2124 for (i
= 0; i
< signature
->element_count
; ++i
)
2126 element
= &signature
->elements
[i
];
2127 location
= element
->register_idx
;
2129 if (!(mask
& (1u << location
)) || element
->sysval_semantic
)
2131 mask
&= ~(1u << location
);
2133 a
= &key
->attributes
[attribute_count
++];
2134 a
->location
= location
;
2135 a
->binding
= null_binding
;
2136 a
->format
= vk_format_from_component_type(element
->component_type
);
2140 if (mask
!= (~stream_info
.use_map
& vertex_shader
->reg_maps
.input_registers
))
2142 b
= &key
->bindings
[binding_count
++];
2143 *null_buffer_binding
= b
->binding
= null_binding
;
2145 b
->inputRate
= VK_VERTEX_INPUT_RATE_VERTEX
;
2150 key
->input_desc
.pNext
= NULL
;
2151 key
->input_desc
.vertexBindingDescriptionCount
= binding_count
;
2152 key
->input_desc
.vertexAttributeDescriptionCount
= attribute_count
;
2156 key
->input_desc
.pNext
= &key
->divisor_desc
;
2157 key
->divisor_desc
.vertexBindingDivisorCount
= divisor_count
;
2163 vk_topology
= vk_topology_from_wined3d(state
->primitive_type
);
2164 if (key
->ia_desc
.topology
!= vk_topology
)
2166 key
->ia_desc
.topology
= vk_topology
;
2167 key
->ia_desc
.primitiveRestartEnable
= !(d3d_info
->wined3d_creation_flags
& WINED3D_NO_PRIMITIVE_RESTART
)
2168 && !wined3d_primitive_type_is_list(state
->primitive_type
);
2173 if (key
->ts_desc
.patchControlPoints
!= state
->patch_vertex_count
)
2175 key
->ts_desc
.patchControlPoints
= state
->patch_vertex_count
;
2180 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_VIEWPORT
)
2181 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SCISSORRECT
)
2182 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_RASTERIZER
))
2184 key
->viewport
.x
= state
->viewports
[0].x
;
2185 key
->viewport
.y
= state
->viewports
[0].y
;
2186 key
->viewport
.width
= state
->viewports
[0].width
;
2187 key
->viewport
.height
= state
->viewports
[0].height
;
2188 key
->viewport
.minDepth
= state
->viewports
[0].min_z
;
2189 key
->viewport
.maxDepth
= state
->viewports
[0].max_z
;
2191 if (state
->rasterizer_state
&& state
->rasterizer_state
->desc
.scissor
)
2193 const RECT
*r
= &state
->scissor_rects
[0];
2195 key
->scissor
.offset
.x
= r
->left
;
2196 key
->scissor
.offset
.y
= r
->top
;
2197 key
->scissor
.extent
.width
= r
->right
- r
->left
;
2198 key
->scissor
.extent
.height
= r
->bottom
- r
->top
;
2202 key
->scissor
.offset
.x
= key
->viewport
.x
;
2203 key
->scissor
.offset
.y
= key
->viewport
.y
;
2204 key
->scissor
.extent
.width
= key
->viewport
.width
;
2205 key
->scissor
.extent
.height
= key
->viewport
.height
;
2207 /* Scissor offsets need to be non-negative (VUID-VkPipelineViewportStateCreateInfo-x-02821) */
2208 if (key
->scissor
.offset
.x
< 0)
2209 key
->scissor
.offset
.x
= 0;
2210 if (key
->scissor
.offset
.y
< 0)
2211 key
->scissor
.offset
.y
= 0;
2212 key
->viewport
.y
+= key
->viewport
.height
;
2213 key
->viewport
.height
= -key
->viewport
.height
;
2218 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_RASTERIZER
)
2219 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
)))
2221 wined3d_context_vk_update_rasterisation_state(context_vk
, state
, key
);
2226 if (key
->ms_desc
.rasterizationSamples
!= context_vk
->sample_count
2227 || isStateDirty(&context_vk
->c
, STATE_BLEND
) || isStateDirty(&context_vk
->c
, STATE_SAMPLE_MASK
))
2229 key
->ms_desc
.rasterizationSamples
= context_vk
->sample_count
;
2230 key
->ms_desc
.alphaToCoverageEnable
= state
->blend_state
&& state
->blend_state
->desc
.alpha_to_coverage
;
2231 key
->sample_mask
= state
->sample_mask
;
2236 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_DEPTH_STENCIL
)
2237 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_FRAMEBUFFER
))
2239 const struct wined3d_depth_stencil_state
*d
= state
->depth_stencil_state
;
2243 key
->ds_desc
.depthTestEnable
= d
->desc
.depth
;
2244 key
->ds_desc
.depthWriteEnable
= d
->desc
.depth_write
;
2245 key
->ds_desc
.depthCompareOp
= vk_compare_op_from_wined3d(d
->desc
.depth_func
);
2246 key
->ds_desc
.stencilTestEnable
= state
->fb
.depth_stencil
&& d
->desc
.stencil
;
2247 if (key
->ds_desc
.stencilTestEnable
)
2249 key
->ds_desc
.front
.failOp
= vk_stencil_op_from_wined3d(d
->desc
.front
.fail_op
);
2250 key
->ds_desc
.front
.passOp
= vk_stencil_op_from_wined3d(d
->desc
.front
.pass_op
);
2251 key
->ds_desc
.front
.depthFailOp
= vk_stencil_op_from_wined3d(d
->desc
.front
.depth_fail_op
);
2252 key
->ds_desc
.front
.compareOp
= vk_compare_op_from_wined3d(d
->desc
.front
.func
);
2253 key
->ds_desc
.front
.compareMask
= d
->desc
.stencil_read_mask
;
2254 key
->ds_desc
.front
.writeMask
= d
->desc
.stencil_write_mask
;
2256 key
->ds_desc
.back
.failOp
= vk_stencil_op_from_wined3d(d
->desc
.back
.fail_op
);
2257 key
->ds_desc
.back
.passOp
= vk_stencil_op_from_wined3d(d
->desc
.back
.pass_op
);
2258 key
->ds_desc
.back
.depthFailOp
= vk_stencil_op_from_wined3d(d
->desc
.back
.depth_fail_op
);
2259 key
->ds_desc
.back
.compareOp
= vk_compare_op_from_wined3d(d
->desc
.back
.func
);
2260 key
->ds_desc
.back
.compareMask
= d
->desc
.stencil_read_mask
;
2261 key
->ds_desc
.back
.writeMask
= d
->desc
.stencil_write_mask
;
2265 memset(&key
->ds_desc
.front
, 0, sizeof(key
->ds_desc
.front
));
2266 memset(&key
->ds_desc
.back
, 0, sizeof(key
->ds_desc
.back
));
2271 key
->ds_desc
.depthTestEnable
= VK_TRUE
;
2272 key
->ds_desc
.depthWriteEnable
= VK_TRUE
;
2273 key
->ds_desc
.depthCompareOp
= VK_COMPARE_OP_LESS
;
2274 key
->ds_desc
.stencilTestEnable
= VK_FALSE
;
2280 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_BLEND
)
2281 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_FRAMEBUFFER
))
2283 wined3d_context_vk_update_blend_state(context_vk
, state
, key
);
2288 if (key
->pipeline_desc
.layout
!= vk_pipeline_layout
)
2290 key
->pipeline_desc
.layout
= vk_pipeline_layout
;
2295 if (key
->pipeline_desc
.renderPass
!= context_vk
->vk_render_pass
)
2297 key
->pipeline_desc
.renderPass
= context_vk
->vk_render_pass
;
2305 static bool wined3d_context_vk_begin_render_pass(struct wined3d_context_vk
*context_vk
,
2306 VkCommandBuffer vk_command_buffer
, const struct wined3d_state
*state
, const struct wined3d_vk_info
*vk_info
)
2308 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
2309 VkImageView vk_views
[WINED3D_MAX_RENDER_TARGETS
+ 1];
2310 unsigned int fb_width
, fb_height
, fb_layer_count
;
2311 struct wined3d_rendertarget_view_vk
*rtv_vk
;
2312 struct wined3d_rendertarget_view
*view
;
2313 const VkPhysicalDeviceLimits
*limits
;
2314 VkRenderPassBeginInfo begin_info
;
2315 unsigned int attachment_count
, i
;
2316 VkFramebufferCreateInfo fb_desc
;
2319 if (context_vk
->vk_render_pass
)
2322 limits
= &wined3d_adapter_vk(device_vk
->d
.adapter
)->device_limits
;
2323 fb_width
= limits
->maxFramebufferWidth
;
2324 fb_height
= limits
->maxFramebufferHeight
;
2325 fb_layer_count
= limits
->maxFramebufferLayers
;
2326 attachment_count
= 0;
2328 context_vk
->rt_count
= 0;
2329 for (i
= 0; i
< ARRAY_SIZE(state
->fb
.render_targets
); ++i
)
2331 if (!(view
= state
->fb
.render_targets
[i
]) || view
->format
->id
== WINED3DFMT_NULL
)
2334 rtv_vk
= wined3d_rendertarget_view_vk(view
);
2335 vk_views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
2336 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_RENDER_TARGET
);
2337 wined3d_context_vk_reference_rendertarget_view(context_vk
, rtv_vk
);
2339 if (view
->width
< fb_width
)
2340 fb_width
= view
->width
;
2341 if (view
->height
< fb_height
)
2342 fb_height
= view
->height
;
2343 if (view
->layer_count
< fb_layer_count
)
2344 fb_layer_count
= view
->layer_count
;
2345 context_vk
->rt_count
= i
+ 1;
2349 if ((view
= state
->fb
.depth_stencil
))
2351 rtv_vk
= wined3d_rendertarget_view_vk(view
);
2352 vk_views
[attachment_count
] = wined3d_rendertarget_view_vk_get_image_view(rtv_vk
, context_vk
);
2353 wined3d_rendertarget_view_vk_barrier(rtv_vk
, context_vk
, WINED3D_BIND_DEPTH_STENCIL
);
2354 wined3d_context_vk_reference_rendertarget_view(context_vk
, rtv_vk
);
2356 if (view
->width
< fb_width
)
2357 fb_width
= view
->width
;
2358 if (view
->height
< fb_height
)
2359 fb_height
= view
->height
;
2360 if (view
->layer_count
< fb_layer_count
)
2361 fb_layer_count
= view
->layer_count
;
2365 if (!(context_vk
->vk_render_pass
= wined3d_context_vk_get_render_pass(context_vk
, &state
->fb
,
2366 ARRAY_SIZE(state
->fb
.render_targets
), !!state
->fb
.depth_stencil
, 0)))
2368 ERR("Failed to get render pass.\n");
2372 fb_desc
.sType
= VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO
;
2373 fb_desc
.pNext
= NULL
;
2375 fb_desc
.renderPass
= context_vk
->vk_render_pass
;
2376 fb_desc
.attachmentCount
= attachment_count
;
2377 fb_desc
.pAttachments
= vk_views
;
2378 fb_desc
.width
= fb_width
;
2379 fb_desc
.height
= fb_height
;
2380 fb_desc
.layers
= fb_layer_count
;
2382 if ((vr
= VK_CALL(vkCreateFramebuffer(device_vk
->vk_device
, &fb_desc
, NULL
, &context_vk
->vk_framebuffer
))) < 0)
2384 WARN("Failed to create Vulkan framebuffer, vr %s.\n", wined3d_debug_vkresult(vr
));
2388 begin_info
.sType
= VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO
;
2389 begin_info
.pNext
= NULL
;
2390 begin_info
.renderPass
= context_vk
->vk_render_pass
;
2391 begin_info
.framebuffer
= context_vk
->vk_framebuffer
;
2392 begin_info
.renderArea
.offset
.x
= 0;
2393 begin_info
.renderArea
.offset
.y
= 0;
2394 begin_info
.renderArea
.extent
.width
= fb_width
;
2395 begin_info
.renderArea
.extent
.height
= fb_height
;
2396 begin_info
.clearValueCount
= 0;
2397 begin_info
.pClearValues
= NULL
;
2398 VK_CALL(vkCmdBeginRenderPass(vk_command_buffer
, &begin_info
, VK_SUBPASS_CONTENTS_INLINE
));
2403 static void wined3d_context_vk_bind_vertex_buffers(struct wined3d_context_vk
*context_vk
,
2404 VkCommandBuffer vk_command_buffer
, const struct wined3d_state
*state
, const struct wined3d_vk_info
*vk_info
)
2406 VkDeviceSize offsets
[ARRAY_SIZE(state
->streams
)] = {0};
2407 VkBuffer buffers
[ARRAY_SIZE(state
->streams
)];
2408 const struct wined3d_stream_state
*stream
;
2409 const VkDescriptorBufferInfo
*buffer_info
;
2410 struct wined3d_buffer_vk
*buffer_vk
;
2411 struct wined3d_buffer
*buffer
;
2412 unsigned int i
, first
, count
;
2416 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
2418 stream
= &state
->streams
[i
];
2420 if ((buffer
= stream
->buffer
))
2422 buffer_vk
= wined3d_buffer_vk(buffer
);
2423 buffer_info
= wined3d_buffer_vk_get_buffer_info(buffer_vk
);
2424 wined3d_context_vk_reference_bo(context_vk
, &buffer_vk
->bo
);
2425 buffers
[count
] = buffer_info
->buffer
;
2426 offsets
[count
] = buffer_info
->offset
+ stream
->offset
;
2432 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer
, first
, count
, buffers
, offsets
));
2438 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer
, first
, count
, buffers
, offsets
));
2441 static void wined3d_context_vk_bind_stream_output_buffers(struct wined3d_context_vk
*context_vk
,
2442 VkCommandBuffer vk_command_buffer
, const struct wined3d_state
*state
, const struct wined3d_vk_info
*vk_info
)
2444 VkDeviceSize offsets
[ARRAY_SIZE(state
->stream_output
)];
2445 VkDeviceSize sizes
[ARRAY_SIZE(state
->stream_output
)];
2446 VkBuffer buffers
[ARRAY_SIZE(state
->stream_output
)];
2447 const struct wined3d_stream_output
*stream
;
2448 const VkDescriptorBufferInfo
*buffer_info
;
2449 struct wined3d_buffer_vk
*buffer_vk
;
2450 struct wined3d_buffer
*buffer
;
2451 unsigned int i
, first
, count
;
2455 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
2457 stream
= &state
->stream_output
[i
];
2459 if ((buffer
= stream
->buffer
))
2461 buffer_vk
= wined3d_buffer_vk(buffer
);
2462 buffer_info
= wined3d_buffer_vk_get_buffer_info(buffer_vk
);
2463 wined3d_context_vk_reference_bo(context_vk
, &buffer_vk
->bo
);
2464 buffers
[count
] = buffer_info
->buffer
;
2465 if ((offsets
[count
] = stream
->offset
) == ~0u)
2467 FIXME("Appending to stream output buffers not implemented.\n");
2470 sizes
[count
] = buffer_info
->range
- offsets
[count
];
2471 offsets
[count
] += buffer_info
->offset
;
2477 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer
, first
, count
, buffers
, offsets
, sizes
));
2483 VK_CALL(vkCmdBindTransformFeedbackBuffersEXT(vk_command_buffer
, first
, count
, buffers
, offsets
, sizes
));
2486 static VkResult
wined3d_context_vk_create_vk_descriptor_pool(struct wined3d_device_vk
*device_vk
,
2487 const struct wined3d_vk_info
*vk_info
, VkDescriptorPool
*vk_pool
)
2489 struct VkDescriptorPoolCreateInfo pool_desc
;
2492 static const VkDescriptorPoolSize pool_sizes
[] =
2494 {VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
, 1024},
2495 {VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
, 1024},
2496 {VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, 1024},
2497 {VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
, 1024},
2498 {VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
, 1024},
2499 {VK_DESCRIPTOR_TYPE_SAMPLER
, 1024},
2502 pool_desc
.sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO
;
2503 pool_desc
.pNext
= NULL
;
2504 pool_desc
.flags
= 0;
2505 pool_desc
.maxSets
= 512;
2506 pool_desc
.poolSizeCount
= ARRAY_SIZE(pool_sizes
);
2507 pool_desc
.pPoolSizes
= pool_sizes
;
2509 if ((vr
= VK_CALL(vkCreateDescriptorPool(device_vk
->vk_device
, &pool_desc
, NULL
, vk_pool
))) < 0)
2510 ERR("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr
));
2515 static VkResult
wined3d_context_vk_create_vk_descriptor_set(struct wined3d_context_vk
*context_vk
,
2516 VkDescriptorSetLayout vk_set_layout
, VkDescriptorSet
*vk_descriptor_set
)
2518 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
2519 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
2520 struct VkDescriptorSetAllocateInfo set_desc
;
2523 if (!context_vk
->vk_descriptor_pool
&& (vr
= wined3d_context_vk_create_vk_descriptor_pool(device_vk
,
2524 vk_info
, &context_vk
->vk_descriptor_pool
)))
2526 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr
));
2530 set_desc
.sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO
;
2531 set_desc
.pNext
= NULL
;
2532 set_desc
.descriptorPool
= context_vk
->vk_descriptor_pool
;
2533 set_desc
.descriptorSetCount
= 1;
2534 set_desc
.pSetLayouts
= &vk_set_layout
;
2535 if ((vr
= VK_CALL(vkAllocateDescriptorSets(device_vk
->vk_device
, &set_desc
, vk_descriptor_set
))) >= 0)
2538 if (vr
== VK_ERROR_FRAGMENTED_POOL
|| vr
== VK_ERROR_OUT_OF_POOL_MEMORY
)
2540 wined3d_context_vk_destroy_vk_descriptor_pool(context_vk
,
2541 context_vk
->vk_descriptor_pool
, context_vk
->current_command_buffer
.id
);
2542 context_vk
->vk_descriptor_pool
= VK_NULL_HANDLE
;
2543 if ((vr
= wined3d_context_vk_create_vk_descriptor_pool(device_vk
, vk_info
, &context_vk
->vk_descriptor_pool
)))
2545 WARN("Failed to create descriptor pool, vr %s.\n", wined3d_debug_vkresult(vr
));
2549 set_desc
.descriptorPool
= context_vk
->vk_descriptor_pool
;
2550 if ((vr
= VK_CALL(vkAllocateDescriptorSets(device_vk
->vk_device
, &set_desc
, vk_descriptor_set
))) >= 0)
2554 WARN("Failed to allocate descriptor set, vr %s.\n", wined3d_debug_vkresult(vr
));
2559 static bool wined3d_shader_descriptor_writes_vk_add_write(struct wined3d_shader_descriptor_writes_vk
*writes
,
2560 VkDescriptorSet vk_descriptor_set
, size_t binding_idx
, VkDescriptorType type
,
2561 const VkDescriptorBufferInfo
*buffer_info
, const VkDescriptorImageInfo
*image_info
,
2562 const VkBufferView
*buffer_view
)
2564 SIZE_T write_count
= writes
->count
;
2565 VkWriteDescriptorSet
*write
;
2567 if (!wined3d_array_reserve((void **)&writes
->writes
, &writes
->size
,
2568 write_count
+ 1, sizeof(*writes
->writes
)))
2571 write
= &writes
->writes
[write_count
];
2572 write
->sType
= VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET
;
2573 write
->pNext
= NULL
;
2574 write
->dstSet
= vk_descriptor_set
;
2575 write
->dstBinding
= binding_idx
;
2576 write
->dstArrayElement
= 0;
2577 write
->descriptorCount
= 1;
2578 write
->descriptorType
= type
;
2579 write
->pImageInfo
= image_info
;
2580 write
->pBufferInfo
= buffer_info
;
2581 write
->pTexelBufferView
= buffer_view
;
2588 static bool wined3d_shader_resource_bindings_add_null_srv_binding(struct wined3d_shader_descriptor_writes_vk
*writes
,
2589 VkDescriptorSet vk_descriptor_set
, size_t binding_idx
, enum wined3d_shader_resource_type type
,
2590 enum wined3d_data_type data_type
, struct wined3d_context_vk
*context_vk
)
2592 const struct wined3d_null_views_vk
*v
= &wined3d_device_vk(context_vk
->c
.device
)->null_views_vk
;
2596 case WINED3D_SHADER_RESOURCE_BUFFER
:
2597 if (data_type
== WINED3D_DATA_FLOAT
)
2598 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
, binding_idx
,
2599 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
, NULL
, NULL
, &v
->vk_view_buffer_float
);
2600 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
, binding_idx
,
2601 VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
, NULL
, NULL
, &v
->vk_view_buffer_uint
);
2603 case WINED3D_SHADER_RESOURCE_TEXTURE_1D
:
2604 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2605 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_1d
, NULL
);
2607 case WINED3D_SHADER_RESOURCE_TEXTURE_2D
:
2608 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2609 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_2d
, NULL
);
2611 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMS
:
2612 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2613 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_2dms
, NULL
);
2615 case WINED3D_SHADER_RESOURCE_TEXTURE_3D
:
2616 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2617 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_3d
, NULL
);
2619 case WINED3D_SHADER_RESOURCE_TEXTURE_CUBE
:
2620 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2621 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_cube
, NULL
);
2623 case WINED3D_SHADER_RESOURCE_TEXTURE_1DARRAY
:
2624 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2625 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_1d_array
, NULL
);
2627 case WINED3D_SHADER_RESOURCE_TEXTURE_2DARRAY
:
2628 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2629 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_2d_array
, NULL
);
2631 case WINED3D_SHADER_RESOURCE_TEXTURE_2DMSARRAY
:
2632 return wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2633 binding_idx
, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
, NULL
, &v
->vk_info_2dms_array
, NULL
);
2636 FIXME("Unhandled resource type %#x.\n", type
);
2641 static bool wined3d_context_vk_update_descriptors(struct wined3d_context_vk
*context_vk
,
2642 VkCommandBuffer vk_command_buffer
, const struct wined3d_state
*state
, enum wined3d_pipeline pipeline
)
2644 struct wined3d_shader_descriptor_writes_vk
*writes
= &context_vk
->descriptor_writes
;
2645 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
2646 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
2647 const struct wined3d_shader_resource_binding
*binding
;
2648 struct wined3d_shader_resource_bindings
*bindings
;
2649 struct wined3d_unordered_access_view_vk
*uav_vk
;
2650 struct wined3d_shader_resource_view_vk
*srv_vk
;
2651 struct wined3d_unordered_access_view
*uav
;
2652 const VkDescriptorBufferInfo
*buffer_info
;
2653 struct wined3d_shader_resource_view
*srv
;
2654 const VkDescriptorImageInfo
*image_info
;
2655 struct wined3d_buffer_vk
*buffer_vk
;
2656 VkDescriptorSetLayout vk_set_layout
;
2657 VkPipelineLayout vk_pipeline_layout
;
2658 struct wined3d_resource
*resource
;
2659 VkPipelineBindPoint vk_bind_point
;
2660 VkDescriptorSet vk_descriptor_set
;
2661 struct wined3d_view_vk
*view_vk
;
2662 struct wined3d_sampler
*sampler
;
2663 struct wined3d_buffer
*buffer
;
2664 VkBufferView
*buffer_view
;
2665 VkDescriptorType type
;
2671 case WINED3D_PIPELINE_GRAPHICS
:
2672 bindings
= &context_vk
->graphics
.bindings
;
2673 vk_bind_point
= VK_PIPELINE_BIND_POINT_GRAPHICS
;
2674 vk_set_layout
= context_vk
->graphics
.vk_set_layout
;
2675 vk_pipeline_layout
= context_vk
->graphics
.vk_pipeline_layout
;
2678 case WINED3D_PIPELINE_COMPUTE
:
2679 bindings
= &context_vk
->compute
.bindings
;
2680 vk_bind_point
= VK_PIPELINE_BIND_POINT_COMPUTE
;
2681 vk_set_layout
= context_vk
->compute
.vk_set_layout
;
2682 vk_pipeline_layout
= context_vk
->compute
.vk_pipeline_layout
;
2686 ERR("Invalid pipeline %#x.\n", pipeline
);
2690 if ((vr
= wined3d_context_vk_create_vk_descriptor_set(context_vk
, vk_set_layout
, &vk_descriptor_set
)))
2692 WARN("Failed to create descriptor set, vr %s.\n", wined3d_debug_vkresult(vr
));
2697 for (i
= 0; i
< bindings
->count
; ++i
)
2699 binding
= &bindings
->bindings
[i
];
2701 switch (binding
->shader_descriptor_type
)
2703 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV
:
2704 if (!(buffer
= state
->cb
[binding
->shader_type
][binding
->resource_idx
]))
2706 if (!wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2707 binding
->binding_idx
, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
,
2708 &device_vk
->null_resources_vk
.buffer_info
, NULL
, NULL
))
2712 buffer_vk
= wined3d_buffer_vk(buffer
);
2713 buffer_info
= wined3d_buffer_vk_get_buffer_info(buffer_vk
);
2714 if (!wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2715 binding
->binding_idx
, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER
, buffer_info
, NULL
, NULL
))
2717 wined3d_context_vk_reference_bo(context_vk
, &buffer_vk
->bo
);
2720 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV
:
2721 if (!(srv
= state
->shader_resource_view
[binding
->shader_type
][binding
->resource_idx
]))
2723 if (!wined3d_shader_resource_bindings_add_null_srv_binding(writes
, vk_descriptor_set
,
2724 binding
->binding_idx
, binding
->resource_type
, binding
->resource_data_type
, context_vk
))
2728 resource
= srv
->resource
;
2730 srv_vk
= wined3d_shader_resource_view_vk(srv
);
2731 view_vk
= &srv_vk
->view_vk
;
2732 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2735 buffer_view
= &view_vk
->u
.vk_buffer_view
;
2736 type
= VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER
;
2740 struct wined3d_texture_vk
*texture_vk
= wined3d_texture_vk(texture_from_resource(resource
));
2742 if (view_vk
->u
.vk_image_info
.imageView
)
2743 image_info
= &view_vk
->u
.vk_image_info
;
2745 image_info
= wined3d_texture_vk_get_default_image_info(texture_vk
, context_vk
);
2747 type
= VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE
;
2750 if (!wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2751 binding
->binding_idx
, type
, NULL
, image_info
, buffer_view
))
2753 wined3d_context_vk_reference_shader_resource_view(context_vk
, srv_vk
);
2756 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV
:
2757 if (!(uav
= state
->unordered_access_view
[pipeline
][binding
->resource_idx
]))
2759 FIXME("NULL unordered access views not implemented.\n");
2762 resource
= uav
->resource
;
2764 uav_vk
= wined3d_unordered_access_view_vk(uav
);
2765 view_vk
= &uav_vk
->view_vk
;
2766 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
2769 buffer_view
= &view_vk
->u
.vk_buffer_view
;
2770 type
= VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
;
2774 struct wined3d_texture_vk
*texture_vk
= wined3d_texture_vk(texture_from_resource(resource
));
2776 if (view_vk
->u
.vk_image_info
.imageView
)
2777 image_info
= &view_vk
->u
.vk_image_info
;
2779 image_info
= wined3d_texture_vk_get_default_image_info(texture_vk
, context_vk
);
2781 type
= VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
;
2784 if (!wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
,
2785 binding
->binding_idx
, type
, NULL
, image_info
, buffer_view
))
2787 wined3d_context_vk_reference_unordered_access_view(context_vk
, uav_vk
);
2790 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER
:
2791 if (!(uav
= state
->unordered_access_view
[pipeline
][binding
->resource_idx
]))
2793 FIXME("NULL unordered access view counters not implemented.\n");
2797 uav_vk
= wined3d_unordered_access_view_vk(uav
);
2798 if (!uav_vk
->vk_counter_view
|| !wined3d_shader_descriptor_writes_vk_add_write(writes
,
2799 vk_descriptor_set
, binding
->binding_idx
, VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER
,
2800 NULL
, NULL
, &uav_vk
->vk_counter_view
))
2804 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER
:
2805 if (!(sampler
= state
->sampler
[binding
->shader_type
][binding
->resource_idx
]))
2806 sampler
= context_vk
->c
.device
->null_sampler
;
2807 if (!wined3d_shader_descriptor_writes_vk_add_write(writes
, vk_descriptor_set
, binding
->binding_idx
,
2808 VK_DESCRIPTOR_TYPE_SAMPLER
, NULL
, &wined3d_sampler_vk(sampler
)->vk_image_info
, NULL
))
2810 wined3d_context_vk_reference_sampler(context_vk
, wined3d_sampler_vk(sampler
));
2814 ERR("Invalid descriptor type %#x.\n", binding
->shader_descriptor_type
);
2819 VK_CALL(vkUpdateDescriptorSets(device_vk
->vk_device
, writes
->count
, writes
->writes
, 0, NULL
));
2820 VK_CALL(vkCmdBindDescriptorSets(vk_command_buffer
, vk_bind_point
,
2821 vk_pipeline_layout
, 0, 1, &vk_descriptor_set
, 0, NULL
));
2826 static VkResult
wined3d_context_vk_create_vk_descriptor_set_layout(struct wined3d_device_vk
*device_vk
,
2827 const struct wined3d_vk_info
*vk_info
, const struct wined3d_pipeline_layout_key_vk
*key
,
2828 VkDescriptorSetLayout
*vk_set_layout
)
2830 VkDescriptorSetLayoutCreateInfo layout_desc
;
2833 layout_desc
.sType
= VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO
;
2834 layout_desc
.pNext
= NULL
;
2835 layout_desc
.flags
= 0;
2836 layout_desc
.bindingCount
= key
->binding_count
;
2837 layout_desc
.pBindings
= key
->bindings
;
2839 if ((vr
= VK_CALL(vkCreateDescriptorSetLayout(device_vk
->vk_device
, &layout_desc
, NULL
, vk_set_layout
))) < 0)
2840 WARN("Failed to create Vulkan descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr
));
2845 struct wined3d_pipeline_layout_vk
*wined3d_context_vk_get_pipeline_layout(
2846 struct wined3d_context_vk
*context_vk
, VkDescriptorSetLayoutBinding
*bindings
, SIZE_T binding_count
)
2848 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
2849 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
2850 struct wined3d_pipeline_layout_key_vk key
;
2851 struct wined3d_pipeline_layout_vk
*layout
;
2852 VkPipelineLayoutCreateInfo layout_desc
;
2853 struct wine_rb_entry
*entry
;
2856 key
.bindings
= bindings
;
2857 key
.binding_count
= binding_count
;
2858 if ((entry
= wine_rb_get(&context_vk
->pipeline_layouts
, &key
)))
2859 return WINE_RB_ENTRY_VALUE(entry
, struct wined3d_pipeline_layout_vk
, entry
);
2861 if (!(layout
= heap_alloc(sizeof(*layout
))))
2864 if (!(layout
->key
.bindings
= heap_alloc(sizeof(*layout
->key
.bindings
) * key
.binding_count
)))
2869 memcpy(layout
->key
.bindings
, key
.bindings
, sizeof(*layout
->key
.bindings
) * key
.binding_count
);
2870 layout
->key
.binding_count
= key
.binding_count
;
2872 if ((vr
= wined3d_context_vk_create_vk_descriptor_set_layout(device_vk
, vk_info
, &key
, &layout
->vk_set_layout
)))
2874 WARN("Failed to create descriptor set layout, vr %s.\n", wined3d_debug_vkresult(vr
));
2878 layout_desc
.sType
= VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO
;
2879 layout_desc
.pNext
= NULL
;
2880 layout_desc
.flags
= 0;
2881 layout_desc
.setLayoutCount
= 1;
2882 layout_desc
.pSetLayouts
= &layout
->vk_set_layout
;
2883 layout_desc
.pushConstantRangeCount
= 0;
2884 layout_desc
.pPushConstantRanges
= NULL
;
2886 if ((vr
= VK_CALL(vkCreatePipelineLayout(device_vk
->vk_device
,
2887 &layout_desc
, NULL
, &layout
->vk_pipeline_layout
))) < 0)
2889 WARN("Failed to create Vulkan pipeline layout, vr %s.\n", wined3d_debug_vkresult(vr
));
2890 VK_CALL(vkDestroyDescriptorSetLayout(device_vk
->vk_device
, layout
->vk_set_layout
, NULL
));
2894 if (wine_rb_put(&context_vk
->pipeline_layouts
, &layout
->key
, &layout
->entry
) == -1)
2896 ERR("Failed to insert pipeline layout.\n");
2897 VK_CALL(vkDestroyPipelineLayout(device_vk
->vk_device
, layout
->vk_pipeline_layout
, NULL
));
2898 VK_CALL(vkDestroyDescriptorSetLayout(device_vk
->vk_device
, layout
->vk_set_layout
, NULL
));
2905 heap_free(layout
->key
.bindings
);
2910 static VkPipeline
wined3d_context_vk_get_graphics_pipeline(struct wined3d_context_vk
*context_vk
)
2912 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
2913 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
2914 struct wined3d_graphics_pipeline_vk
*pipeline_vk
;
2915 struct wined3d_graphics_pipeline_key_vk
*key
;
2916 struct wine_rb_entry
*entry
;
2919 key
= &context_vk
->graphics
.pipeline_key_vk
;
2920 if ((entry
= wine_rb_get(&context_vk
->graphics_pipelines
, key
)))
2921 return WINE_RB_ENTRY_VALUE(entry
, struct wined3d_graphics_pipeline_vk
, entry
)->vk_pipeline
;
2923 if (!(pipeline_vk
= heap_alloc(sizeof(*pipeline_vk
))))
2924 return VK_NULL_HANDLE
;
2925 pipeline_vk
->key
= *key
;
2927 if ((vr
= VK_CALL(vkCreateGraphicsPipelines(device_vk
->vk_device
,
2928 VK_NULL_HANDLE
, 1, &key
->pipeline_desc
, NULL
, &pipeline_vk
->vk_pipeline
))) < 0)
2930 WARN("Failed to create graphics pipeline, vr %s.\n", wined3d_debug_vkresult(vr
));
2931 heap_free(pipeline_vk
);
2932 return VK_NULL_HANDLE
;
2935 if (wine_rb_put(&context_vk
->graphics_pipelines
, &pipeline_vk
->key
, &pipeline_vk
->entry
) == -1)
2936 ERR("Failed to insert pipeline.\n");
2938 return pipeline_vk
->vk_pipeline
;
2941 static void wined3d_context_vk_load_shader_resources(struct wined3d_context_vk
*context_vk
,
2942 const struct wined3d_state
*state
, enum wined3d_pipeline pipeline
)
2944 struct wined3d_shader_descriptor_writes_vk
*writes
= &context_vk
->descriptor_writes
;
2945 const struct wined3d_shader_resource_bindings
*bindings
;
2946 const struct wined3d_shader_resource_binding
*binding
;
2947 struct wined3d_unordered_access_view_vk
*uav_vk
;
2948 struct wined3d_shader_resource_view_vk
*srv_vk
;
2949 struct wined3d_unordered_access_view
*uav
;
2950 struct wined3d_shader_resource_view
*srv
;
2951 struct wined3d_buffer_vk
*buffer_vk
;
2952 struct wined3d_sampler
*sampler
;
2953 struct wined3d_buffer
*buffer
;
2958 case WINED3D_PIPELINE_GRAPHICS
:
2959 bindings
= &context_vk
->graphics
.bindings
;
2962 case WINED3D_PIPELINE_COMPUTE
:
2963 bindings
= &context_vk
->compute
.bindings
;
2967 ERR("Invalid pipeline %#x.\n", pipeline
);
2972 for (i
= 0; i
< bindings
->count
; ++i
)
2974 binding
= &bindings
->bindings
[i
];
2976 switch (binding
->shader_descriptor_type
)
2978 case WINED3D_SHADER_DESCRIPTOR_TYPE_CBV
:
2979 if (!(buffer
= state
->cb
[binding
->shader_type
][binding
->resource_idx
]))
2982 buffer_vk
= wined3d_buffer_vk(buffer
);
2983 wined3d_buffer_load(buffer
, &context_vk
->c
, state
);
2984 if (!buffer_vk
->bo_user
.valid
)
2986 if (pipeline
== WINED3D_PIPELINE_GRAPHICS
)
2987 context_invalidate_state(&context_vk
->c
, STATE_GRAPHICS_CONSTANT_BUFFER(binding
->shader_type
));
2989 context_invalidate_compute_state(&context_vk
->c
, STATE_COMPUTE_CONSTANT_BUFFER
);
2991 wined3d_buffer_vk_barrier(buffer_vk
, context_vk
, WINED3D_BIND_CONSTANT_BUFFER
);
2994 case WINED3D_SHADER_DESCRIPTOR_TYPE_SRV
:
2995 if (!(srv
= state
->shader_resource_view
[binding
->shader_type
][binding
->resource_idx
]))
2998 srv_vk
= wined3d_shader_resource_view_vk(srv
);
2999 if (srv
->resource
->type
== WINED3D_RTYPE_BUFFER
)
3001 if (!srv_vk
->view_vk
.bo_user
.valid
)
3003 wined3d_shader_resource_view_vk_update(srv_vk
, context_vk
);
3004 if (pipeline
== WINED3D_PIPELINE_GRAPHICS
)
3005 context_invalidate_state(&context_vk
->c
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
);
3007 context_invalidate_compute_state(&context_vk
->c
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
);
3009 wined3d_buffer_load(buffer_from_resource(srv
->resource
), &context_vk
->c
, state
);
3013 wined3d_texture_load(texture_from_resource(srv
->resource
), &context_vk
->c
, FALSE
);
3015 wined3d_shader_resource_view_vk_barrier(srv_vk
, context_vk
, WINED3D_BIND_SHADER_RESOURCE
);
3018 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV
:
3019 if (!(uav
= state
->unordered_access_view
[pipeline
][binding
->resource_idx
]))
3022 uav_vk
= wined3d_unordered_access_view_vk(uav
);
3023 if (uav
->resource
->type
== WINED3D_RTYPE_BUFFER
)
3025 if (!uav_vk
->view_vk
.bo_user
.valid
)
3027 wined3d_unordered_access_view_vk_update(uav_vk
, context_vk
);
3028 if (pipeline
== WINED3D_PIPELINE_GRAPHICS
)
3029 context_invalidate_state(&context_vk
->c
, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING
);
3031 context_invalidate_compute_state(&context_vk
->c
,
3032 STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING
);
3034 wined3d_buffer_load(buffer_from_resource(uav
->resource
), &context_vk
->c
, state
);
3035 wined3d_unordered_access_view_invalidate_location(uav
, ~WINED3D_LOCATION_BUFFER
);
3039 wined3d_texture_load(texture_from_resource(uav
->resource
), &context_vk
->c
, FALSE
);
3040 wined3d_unordered_access_view_invalidate_location(uav
, ~WINED3D_LOCATION_TEXTURE_RGB
);
3042 wined3d_unordered_access_view_vk_barrier(uav_vk
, context_vk
, WINED3D_BIND_UNORDERED_ACCESS
);
3045 case WINED3D_SHADER_DESCRIPTOR_TYPE_UAV_COUNTER
:
3048 case WINED3D_SHADER_DESCRIPTOR_TYPE_SAMPLER
:
3049 if (!(sampler
= state
->sampler
[binding
->shader_type
][binding
->resource_idx
]))
3050 sampler
= context_vk
->c
.device
->null_sampler
;
3054 ERR("Invalid descriptor type %#x.\n", binding
->shader_descriptor_type
);
3060 VkCommandBuffer
wined3d_context_vk_apply_draw_state(struct wined3d_context_vk
*context_vk
,
3061 const struct wined3d_state
*state
, struct wined3d_buffer_vk
*indirect_vk
, bool indexed
)
3063 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
3064 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
3065 struct wined3d_rendertarget_view
*dsv
;
3066 struct wined3d_buffer_vk
*buffer_vk
;
3067 VkSampleCountFlagBits sample_count
;
3068 VkCommandBuffer vk_command_buffer
;
3069 struct wined3d_buffer
*buffer
;
3070 uint32_t null_buffer_binding
;
3073 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
))
3074 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_FRAMEBUFFER
))
3075 context_vk
->c
.shader_update_mask
|= (1u << WINED3D_SHADER_TYPE_PIXEL
);
3076 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_VERTEX
)))
3077 context_vk
->c
.shader_update_mask
|= (1u << WINED3D_SHADER_TYPE_VERTEX
);
3078 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
)))
3079 context_vk
->c
.shader_update_mask
|= (1u << WINED3D_SHADER_TYPE_GEOMETRY
);
3080 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_HULL
)))
3081 context_vk
->c
.shader_update_mask
|= (1u << WINED3D_SHADER_TYPE_HULL
) | (1u << WINED3D_SHADER_TYPE_DOMAIN
);
3082 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN
)))
3083 context_vk
->c
.shader_update_mask
|= (1u << WINED3D_SHADER_TYPE_DOMAIN
);
3085 context_vk
->sample_count
= 0;
3086 for (i
= 0; i
< ARRAY_SIZE(state
->fb
.render_targets
); ++i
)
3088 struct wined3d_rendertarget_view
*rtv
;
3090 if (!(rtv
= state
->fb
.render_targets
[i
]) || rtv
->format
->id
== WINED3DFMT_NULL
)
3093 if (wined3d_blend_state_get_writemask(state
->blend_state
, i
))
3095 wined3d_rendertarget_view_load_location(rtv
, &context_vk
->c
, rtv
->resource
->draw_binding
);
3096 wined3d_rendertarget_view_invalidate_location(rtv
, ~rtv
->resource
->draw_binding
);
3100 wined3d_rendertarget_view_prepare_location(rtv
, &context_vk
->c
, rtv
->resource
->draw_binding
);
3103 sample_count
= max(1, wined3d_resource_get_sample_count(rtv
->resource
));
3104 if (!context_vk
->sample_count
)
3105 context_vk
->sample_count
= sample_count
;
3106 else if (context_vk
->sample_count
!= sample_count
)
3107 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk
->sample_count
, sample_count
);
3110 if ((dsv
= state
->fb
.depth_stencil
))
3112 if (wined3d_state_uses_depth_buffer(state
))
3113 wined3d_rendertarget_view_load_location(dsv
, &context_vk
->c
, dsv
->resource
->draw_binding
);
3115 wined3d_rendertarget_view_prepare_location(dsv
, &context_vk
->c
, dsv
->resource
->draw_binding
);
3116 if (!state
->depth_stencil_state
|| state
->depth_stencil_state
->desc
.depth_write
)
3117 wined3d_rendertarget_view_invalidate_location(dsv
, ~dsv
->resource
->draw_binding
);
3119 sample_count
= max(1, wined3d_resource_get_sample_count(dsv
->resource
));
3120 if (!context_vk
->sample_count
)
3121 context_vk
->sample_count
= sample_count
;
3122 else if (context_vk
->sample_count
!= sample_count
)
3123 FIXME("Inconsistent sample counts (%u != %u).\n", context_vk
->sample_count
, sample_count
);
3126 if (!context_vk
->sample_count
)
3127 context_vk
->sample_count
= VK_SAMPLE_COUNT_1_BIT
;
3128 if (context_vk
->c
.shader_update_mask
& ~(1u << WINED3D_SHADER_TYPE_COMPUTE
))
3130 device_vk
->d
.shader_backend
->shader_select(device_vk
->d
.shader_priv
, &context_vk
->c
, state
);
3131 if (!context_vk
->graphics
.vk_pipeline_layout
)
3133 ERR("No pipeline layout set.\n");
3134 return VK_NULL_HANDLE
;
3136 context_vk
->c
.update_shader_resource_bindings
= 1;
3137 context_vk
->c
.update_unordered_access_view_bindings
= 1;
3140 wined3d_context_vk_load_shader_resources(context_vk
, state
, WINED3D_PIPELINE_GRAPHICS
);
3142 for (i
= 0; i
< ARRAY_SIZE(state
->streams
); ++i
)
3144 if (!(buffer
= state
->streams
[i
].buffer
))
3147 buffer_vk
= wined3d_buffer_vk(buffer
);
3148 wined3d_buffer_load(&buffer_vk
->b
, &context_vk
->c
, state
);
3149 wined3d_buffer_vk_barrier(buffer_vk
, context_vk
, WINED3D_BIND_VERTEX_BUFFER
);
3150 if (!buffer_vk
->bo_user
.valid
)
3151 context_invalidate_state(&context_vk
->c
, STATE_STREAMSRC
);
3154 if (use_transform_feedback(state
) && vk_info
->supported
[WINED3D_VK_EXT_TRANSFORM_FEEDBACK
])
3156 for (i
= 0; i
< ARRAY_SIZE(state
->stream_output
); ++i
)
3158 if (!(buffer
= state
->stream_output
[i
].buffer
))
3161 buffer_vk
= wined3d_buffer_vk(buffer
);
3162 wined3d_buffer_load(&buffer_vk
->b
, &context_vk
->c
, state
);
3163 wined3d_buffer_vk_barrier(buffer_vk
, context_vk
, WINED3D_BIND_STREAM_OUTPUT
);
3164 wined3d_buffer_invalidate_location(&buffer_vk
->b
, ~WINED3D_LOCATION_BUFFER
);
3165 if (!buffer_vk
->bo_user
.valid
)
3166 context_vk
->update_stream_output
= 1;
3168 context_vk
->c
.transform_feedback_active
= 1;
3171 if (indexed
|| (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_INDEXBUFFER
) && state
->index_buffer
))
3173 buffer_vk
= wined3d_buffer_vk(state
->index_buffer
);
3174 wined3d_buffer_load(&buffer_vk
->b
, &context_vk
->c
, state
);
3175 wined3d_buffer_vk_barrier(buffer_vk
, context_vk
, WINED3D_BIND_INDEX_BUFFER
);
3176 if (!buffer_vk
->bo_user
.valid
)
3177 context_invalidate_state(&context_vk
->c
, STATE_INDEXBUFFER
);
3182 wined3d_buffer_load(&indirect_vk
->b
, &context_vk
->c
, state
);
3183 wined3d_buffer_vk_barrier(indirect_vk
, context_vk
, WINED3D_BIND_INDIRECT_BUFFER
);
3186 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
3188 ERR("Failed to get command buffer.\n");
3189 return VK_NULL_HANDLE
;
3192 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_FRAMEBUFFER
))
3193 wined3d_context_vk_end_current_render_pass(context_vk
);
3194 if (!wined3d_context_vk_begin_render_pass(context_vk
, vk_command_buffer
, state
, vk_info
))
3196 ERR("Failed to begin render pass.\n");
3197 return VK_NULL_HANDLE
;
3200 if (wined3d_context_vk_update_graphics_pipeline_key(context_vk
, state
, context_vk
->graphics
.vk_pipeline_layout
,
3201 &null_buffer_binding
) || !context_vk
->graphics
.vk_pipeline
)
3203 if (!(context_vk
->graphics
.vk_pipeline
= wined3d_context_vk_get_graphics_pipeline(context_vk
)))
3205 ERR("Failed to get graphics pipeline.\n");
3206 return VK_NULL_HANDLE
;
3209 VK_CALL(vkCmdBindPipeline(vk_command_buffer
,
3210 VK_PIPELINE_BIND_POINT_GRAPHICS
, context_vk
->graphics
.vk_pipeline
));
3211 if (null_buffer_binding
!= ~0u)
3213 VkDeviceSize offset
= 0;
3214 VK_CALL(vkCmdBindVertexBuffers(vk_command_buffer
, null_buffer_binding
, 1,
3215 &device_vk
->null_resources_vk
.buffer_info
.buffer
, &offset
));
3219 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_STENCIL_REF
) && dsv
)
3221 VK_CALL(vkCmdSetStencilReference(vk_command_buffer
, VK_STENCIL_FACE_FRONT_AND_BACK
,
3222 state
->stencil_ref
& ((1 << dsv
->format
->stencil_size
) - 1)));
3225 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_STREAMSRC
))
3226 wined3d_context_vk_bind_vertex_buffers(context_vk
, vk_command_buffer
, state
, vk_info
);
3228 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_STREAM_OUTPUT
))
3230 context_vk
->update_stream_output
= 1;
3231 context_vk
->c
.transform_feedback_paused
= 0;
3233 if (context_vk
->c
.transform_feedback_active
&& context_vk
->update_stream_output
)
3235 wined3d_context_vk_bind_stream_output_buffers(context_vk
, vk_command_buffer
, state
, vk_info
);
3236 context_vk
->update_stream_output
= 0;
3239 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_INDEXBUFFER
) && state
->index_buffer
)
3241 const VkDescriptorBufferInfo
*buffer_info
;
3242 VkIndexType idx_type
;
3244 if (state
->index_format
== WINED3DFMT_R16_UINT
)
3245 idx_type
= VK_INDEX_TYPE_UINT16
;
3247 idx_type
= VK_INDEX_TYPE_UINT32
;
3248 buffer_vk
= wined3d_buffer_vk(state
->index_buffer
);
3249 buffer_info
= wined3d_buffer_vk_get_buffer_info(buffer_vk
);
3250 wined3d_context_vk_reference_bo(context_vk
, &buffer_vk
->bo
);
3251 VK_CALL(vkCmdBindIndexBuffer(vk_command_buffer
, buffer_info
->buffer
,
3252 buffer_info
->offset
+ state
->index_offset
, idx_type
));
3255 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL
))
3256 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
,
3257 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX
))
3258 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
,
3259 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY
))
3260 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
,
3261 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL
))
3262 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
,
3263 STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN
))
3264 || wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_GRAPHICS_SHADER_RESOURCE_BINDING
))
3265 context_vk
->c
.update_shader_resource_bindings
= 1;
3266 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING
))
3267 context_vk
->c
.update_unordered_access_view_bindings
= 1;
3269 if (context_vk
->c
.update_shader_resource_bindings
|| context_vk
->c
.update_unordered_access_view_bindings
)
3271 if (!wined3d_context_vk_update_descriptors(context_vk
, vk_command_buffer
, state
, WINED3D_PIPELINE_GRAPHICS
))
3273 ERR("Failed to update shader descriptors.\n");
3274 return VK_NULL_HANDLE
;
3277 context_vk
->c
.update_shader_resource_bindings
= 0;
3278 context_vk
->c
.update_unordered_access_view_bindings
= 0;
3281 if (wined3d_context_is_graphics_state_dirty(&context_vk
->c
, STATE_BLEND_FACTOR
))
3282 VK_CALL(vkCmdSetBlendConstants(vk_command_buffer
, &state
->blend_factor
.r
));
3284 memset(context_vk
->c
.dirty_graphics_states
, 0, sizeof(context_vk
->c
.dirty_graphics_states
));
3285 context_vk
->c
.shader_update_mask
&= 1u << WINED3D_SHADER_TYPE_COMPUTE
;
3287 return vk_command_buffer
;
3290 VkCommandBuffer
wined3d_context_vk_apply_compute_state(struct wined3d_context_vk
*context_vk
,
3291 const struct wined3d_state
*state
, struct wined3d_buffer_vk
*indirect_vk
)
3293 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
3294 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
3295 VkCommandBuffer vk_command_buffer
;
3297 wined3d_context_vk_end_current_render_pass(context_vk
);
3299 if (wined3d_context_is_compute_state_dirty(&context_vk
->c
, STATE_COMPUTE_SHADER
))
3300 context_vk
->c
.shader_update_mask
|= 1u << WINED3D_SHADER_TYPE_COMPUTE
;
3302 if (context_vk
->c
.shader_update_mask
& (1u << WINED3D_SHADER_TYPE_COMPUTE
))
3304 device_vk
->d
.shader_backend
->shader_select_compute(device_vk
->d
.shader_priv
, &context_vk
->c
, state
);
3305 if (!context_vk
->compute
.vk_pipeline
)
3307 ERR("No compute pipeline set.\n");
3308 return VK_NULL_HANDLE
;
3310 context_vk
->c
.update_compute_shader_resource_bindings
= 1;
3311 context_vk
->c
.update_compute_unordered_access_view_bindings
= 1;
3312 context_vk
->update_compute_pipeline
= 1;
3315 wined3d_context_vk_load_shader_resources(context_vk
, state
, WINED3D_PIPELINE_COMPUTE
);
3319 wined3d_buffer_load_location(&indirect_vk
->b
, &context_vk
->c
, WINED3D_LOCATION_BUFFER
);
3320 wined3d_buffer_vk_barrier(indirect_vk
, context_vk
, WINED3D_BIND_INDIRECT_BUFFER
);
3323 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
3325 ERR("Failed to get command buffer.\n");
3326 return VK_NULL_HANDLE
;
3329 if (context_vk
->update_compute_pipeline
)
3331 VK_CALL(vkCmdBindPipeline(vk_command_buffer
,
3332 VK_PIPELINE_BIND_POINT_COMPUTE
, context_vk
->compute
.vk_pipeline
));
3333 context_vk
->update_compute_pipeline
= 0;
3336 if (wined3d_context_is_compute_state_dirty(&context_vk
->c
, STATE_COMPUTE_CONSTANT_BUFFER
)
3337 || wined3d_context_is_compute_state_dirty(&context_vk
->c
, STATE_COMPUTE_SHADER_RESOURCE_BINDING
))
3338 context_vk
->c
.update_compute_shader_resource_bindings
= 1;
3339 if (wined3d_context_is_compute_state_dirty(&context_vk
->c
, STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING
))
3340 context_vk
->c
.update_compute_unordered_access_view_bindings
= 1;
3342 if (context_vk
->c
.update_compute_shader_resource_bindings
3343 || context_vk
->c
.update_compute_unordered_access_view_bindings
)
3345 if (!wined3d_context_vk_update_descriptors(context_vk
, vk_command_buffer
, state
, WINED3D_PIPELINE_COMPUTE
))
3347 ERR("Failed to update shader descriptors.\n");
3348 return VK_NULL_HANDLE
;
3351 context_vk
->c
.update_compute_shader_resource_bindings
= 0;
3352 context_vk
->c
.update_compute_unordered_access_view_bindings
= 0;
3355 memset(context_vk
->c
.dirty_compute_states
, 0, sizeof(context_vk
->c
.dirty_compute_states
));
3356 context_vk
->c
.shader_update_mask
&= ~(1u << WINED3D_SHADER_TYPE_COMPUTE
);
3358 return vk_command_buffer
;
3361 HRESULT
wined3d_context_vk_init(struct wined3d_context_vk
*context_vk
, struct wined3d_swapchain
*swapchain
)
3363 VkCommandPoolCreateInfo command_pool_info
;
3364 const struct wined3d_vk_info
*vk_info
;
3365 struct wined3d_adapter_vk
*adapter_vk
;
3366 struct wined3d_device_vk
*device_vk
;
3369 TRACE("context_vk %p, swapchain %p.\n", context_vk
, swapchain
);
3371 memset(context_vk
, 0, sizeof(*context_vk
));
3372 wined3d_context_init(&context_vk
->c
, swapchain
);
3373 device_vk
= wined3d_device_vk(swapchain
->device
);
3374 adapter_vk
= wined3d_adapter_vk(device_vk
->d
.adapter
);
3375 context_vk
->vk_info
= vk_info
= &adapter_vk
->vk_info
;
3377 command_pool_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
;
3378 command_pool_info
.pNext
= NULL
;
3379 command_pool_info
.flags
= VK_COMMAND_POOL_CREATE_TRANSIENT_BIT
;
3380 command_pool_info
.queueFamilyIndex
= device_vk
->vk_queue_family_index
;
3381 if ((vr
= VK_CALL(vkCreateCommandPool(device_vk
->vk_device
,
3382 &command_pool_info
, NULL
, &context_vk
->vk_command_pool
))) < 0)
3384 ERR("Failed to create Vulkan command pool, vr %s.\n", wined3d_debug_vkresult(vr
));
3385 wined3d_context_cleanup(&context_vk
->c
);
3388 context_vk
->current_command_buffer
.id
= 1;
3390 wined3d_context_vk_init_graphics_pipeline_key(context_vk
);
3392 list_init(&context_vk
->active_queries
);
3393 list_init(&context_vk
->free_occlusion_query_pools
);
3394 list_init(&context_vk
->free_timestamp_query_pools
);
3395 list_init(&context_vk
->free_pipeline_statistics_query_pools
);
3396 list_init(&context_vk
->free_stream_output_statistics_query_pools
);
3398 wine_rb_init(&context_vk
->render_passes
, wined3d_render_pass_vk_compare
);
3399 wine_rb_init(&context_vk
->pipeline_layouts
, wined3d_pipeline_layout_vk_compare
);
3400 wine_rb_init(&context_vk
->graphics_pipelines
, wined3d_graphics_pipeline_vk_compare
);
3401 wine_rb_init(&context_vk
->bo_slab_available
, wined3d_bo_slab_vk_compare
);