2 * Copyright 2018 Henri Verbeet for CodeWeavers
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 #include "wined3d_private.h"
20 #include "wined3d_vk.h"
22 WINE_DEFAULT_DEBUG_CHANNEL(d3d
);
24 static const struct wined3d_state_entry_template misc_state_template_vk
[] =
26 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_VERTEX
), state_nop
}},
27 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_HULL
), state_nop
}},
28 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_DOMAIN
), state_nop
}},
29 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_GEOMETRY
), state_nop
}},
30 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_PIXEL
), state_nop
}},
31 {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE
), {STATE_CONSTANT_BUFFER(WINED3D_SHADER_TYPE_COMPUTE
), state_nop
}},
32 {STATE_GRAPHICS_SHADER_RESOURCE_BINDING
, {STATE_GRAPHICS_SHADER_RESOURCE_BINDING
, state_nop
}},
33 {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING
, {STATE_GRAPHICS_UNORDERED_ACCESS_VIEW_BINDING
, state_nop
}},
34 {STATE_COMPUTE_SHADER_RESOURCE_BINDING
, {STATE_COMPUTE_SHADER_RESOURCE_BINDING
, state_nop
}},
35 {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING
, {STATE_COMPUTE_UNORDERED_ACCESS_VIEW_BINDING
, state_nop
}},
36 {STATE_STREAM_OUTPUT
, {STATE_STREAM_OUTPUT
, state_nop
}},
37 {STATE_BLEND
, {STATE_BLEND
, state_nop
}},
38 {STATE_BLEND_FACTOR
, {STATE_BLEND_FACTOR
, state_nop
}},
39 {STATE_SAMPLE_MASK
, {STATE_SAMPLE_MASK
, state_nop
}},
40 {STATE_STREAMSRC
, {STATE_STREAMSRC
, state_nop
}},
41 {STATE_VDECL
, {STATE_VDECL
, state_nop
}},
42 {STATE_DEPTH_STENCIL
, {STATE_DEPTH_STENCIL
, state_nop
}},
43 {STATE_STENCIL_REF
, {STATE_STENCIL_REF
, state_nop
}},
44 {STATE_DEPTH_BOUNDS
, {STATE_DEPTH_BOUNDS
, state_nop
}},
45 {STATE_RASTERIZER
, {STATE_RASTERIZER
, state_nop
}},
46 {STATE_SCISSORRECT
, {STATE_SCISSORRECT
, state_nop
}},
47 {STATE_POINTSPRITECOORDORIGIN
, {STATE_POINTSPRITECOORDORIGIN
, state_nop
}},
49 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
50 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00
)}},
51 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00
)}},
52 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_MAT00
)}},
53 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
54 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00
)}},
55 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00
)}},
56 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_MAT00
)}},
57 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
58 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00
)}},
59 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00
)}},
60 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_MAT00
)}},
61 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
62 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00
)}},
63 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00
)}},
64 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_MAT00
)}},
65 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
66 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00
)}},
67 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00
)}},
68 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_MAT00
)}},
69 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
70 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00
)}},
71 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00
)}},
72 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_MAT00
)}},
73 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
74 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00
)}},
75 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00
)}},
76 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_MAT00
)}},
77 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00
), state_nop
}},
78 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT01
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00
)}},
79 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT10
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00
)}},
80 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT11
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_MAT00
)}},
81 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
82 {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(0, WINED3D_TSS_BUMPENV_LSCALE
)}},
83 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
84 {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(1, WINED3D_TSS_BUMPENV_LSCALE
)}},
85 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
86 {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(2, WINED3D_TSS_BUMPENV_LSCALE
)}},
87 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
88 {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(3, WINED3D_TSS_BUMPENV_LSCALE
)}},
89 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
90 {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(4, WINED3D_TSS_BUMPENV_LSCALE
)}},
91 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
92 {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(5, WINED3D_TSS_BUMPENV_LSCALE
)}},
93 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
94 {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(6, WINED3D_TSS_BUMPENV_LSCALE
)}},
95 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE
), state_nop
}},
96 {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LOFFSET
), {STATE_TEXTURESTAGE(7, WINED3D_TSS_BUMPENV_LSCALE
)}},
98 {STATE_VIEWPORT
, {STATE_VIEWPORT
, state_nop
}},
99 {STATE_INDEXBUFFER
, {STATE_INDEXBUFFER
, state_nop
}},
100 {STATE_RENDER(WINED3D_RS_LINEPATTERN
), {STATE_RENDER(WINED3D_RS_LINEPATTERN
), state_nop
}},
101 {STATE_RENDER(WINED3D_RS_DITHERENABLE
), {STATE_RENDER(WINED3D_RS_DITHERENABLE
), state_nop
}},
102 {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS
), {STATE_RENDER(WINED3D_RS_MULTISAMPLEANTIALIAS
), state_nop
}},
104 {STATE_SAMPLER(0), {STATE_SAMPLER(0), state_nop
}},
105 {STATE_SAMPLER(1), {STATE_SAMPLER(1), state_nop
}},
106 {STATE_SAMPLER(2), {STATE_SAMPLER(2), state_nop
}},
107 {STATE_SAMPLER(3), {STATE_SAMPLER(3), state_nop
}},
108 {STATE_SAMPLER(4), {STATE_SAMPLER(4), state_nop
}},
109 {STATE_SAMPLER(5), {STATE_SAMPLER(5), state_nop
}},
110 {STATE_SAMPLER(6), {STATE_SAMPLER(6), state_nop
}},
111 {STATE_SAMPLER(7), {STATE_SAMPLER(7), state_nop
}},
112 {STATE_SAMPLER(8), {STATE_SAMPLER(8), state_nop
}},
113 {STATE_SAMPLER(9), {STATE_SAMPLER(9), state_nop
}},
114 {STATE_SAMPLER(10), {STATE_SAMPLER(10), state_nop
}},
115 {STATE_SAMPLER(11), {STATE_SAMPLER(11), state_nop
}},
116 {STATE_SAMPLER(12), {STATE_SAMPLER(12), state_nop
}},
117 {STATE_SAMPLER(13), {STATE_SAMPLER(13), state_nop
}},
118 {STATE_SAMPLER(14), {STATE_SAMPLER(14), state_nop
}},
119 {STATE_SAMPLER(15), {STATE_SAMPLER(15), state_nop
}},
120 {STATE_SAMPLER(16), /* Vertex sampler 0 */ {STATE_SAMPLER(16), state_nop
}},
121 {STATE_SAMPLER(17), /* Vertex sampler 1 */ {STATE_SAMPLER(17), state_nop
}},
122 {STATE_SAMPLER(18), /* Vertex sampler 2 */ {STATE_SAMPLER(18), state_nop
}},
123 {STATE_SAMPLER(19), /* Vertex sampler 3 */ {STATE_SAMPLER(19), state_nop
}},
124 {STATE_BASEVERTEXINDEX
, {STATE_STREAMSRC
}},
125 {STATE_FRAMEBUFFER
, {STATE_FRAMEBUFFER
, state_nop
}},
126 {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
), {STATE_SHADER(WINED3D_SHADER_TYPE_PIXEL
), state_nop
}},
127 {STATE_SHADER(WINED3D_SHADER_TYPE_HULL
), {STATE_SHADER(WINED3D_SHADER_TYPE_HULL
), state_nop
}},
128 {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN
), {STATE_SHADER(WINED3D_SHADER_TYPE_DOMAIN
), state_nop
}},
129 {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
), {STATE_SHADER(WINED3D_SHADER_TYPE_GEOMETRY
), state_nop
}},
130 {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE
), {STATE_SHADER(WINED3D_SHADER_TYPE_COMPUTE
), state_nop
}},
134 static inline const struct wined3d_adapter_vk
*wined3d_adapter_vk_const(const struct wined3d_adapter
*adapter
)
136 return CONTAINING_RECORD(adapter
, struct wined3d_adapter_vk
, a
);
139 static const char *debug_vk_version(uint32_t version
)
141 return wine_dbg_sprintf("%u.%u.%u",
142 VK_VERSION_MAJOR(version
), VK_VERSION_MINOR(version
), VK_VERSION_PATCH(version
));
145 static HRESULT
hresult_from_vk_result(VkResult vr
)
151 case VK_ERROR_OUT_OF_HOST_MEMORY
:
152 WARN("Out of host memory.\n");
153 return E_OUTOFMEMORY
;
154 case VK_ERROR_OUT_OF_DEVICE_MEMORY
:
155 WARN("Out of device memory.\n");
156 return E_OUTOFMEMORY
;
157 case VK_ERROR_DEVICE_LOST
:
158 WARN("Device lost.\n");
160 case VK_ERROR_EXTENSION_NOT_PRESENT
:
161 WARN("Extension not present.\n");
164 FIXME("Unhandled VkResult %d.\n", vr
);
169 static BOOL
wined3d_load_vulkan(struct wined3d_vk_info
*vk_info
)
171 struct vulkan_ops
*vk_ops
= &vk_info
->vk_ops
;
173 if (!(vk_info
->vulkan_lib
= LoadLibraryA("winevulkan.dll"))
174 && !(vk_info
->vulkan_lib
= LoadLibraryA("vulkan-1.dll")))
176 WARN("Failed to load vulkan-1.dll.\n");
180 vk_ops
->vkGetInstanceProcAddr
= (void *)GetProcAddress(vk_info
->vulkan_lib
, "vkGetInstanceProcAddr");
181 if (!vk_ops
->vkGetInstanceProcAddr
)
183 FreeLibrary(vk_info
->vulkan_lib
);
190 static void wined3d_unload_vulkan(struct wined3d_vk_info
*vk_info
)
192 if (vk_info
->vulkan_lib
)
194 FreeLibrary(vk_info
->vulkan_lib
);
195 vk_info
->vulkan_lib
= NULL
;
199 static void adapter_vk_destroy(struct wined3d_adapter
*adapter
)
201 struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk(adapter
);
202 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
204 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
205 wined3d_unload_vulkan(vk_info
);
206 wined3d_adapter_cleanup(&adapter_vk
->a
);
207 heap_free(adapter_vk
->device_extensions
);
208 heap_free(adapter_vk
);
211 static HRESULT
wined3d_select_vulkan_queue_family(const struct wined3d_adapter_vk
*adapter_vk
,
212 uint32_t *queue_family_index
, uint32_t *timestamp_bits
)
214 VkPhysicalDevice physical_device
= adapter_vk
->physical_device
;
215 const struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
216 VkQueueFamilyProperties
*queue_properties
;
219 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device
, &count
, NULL
));
221 if (!(queue_properties
= heap_calloc(count
, sizeof(*queue_properties
))))
222 return E_OUTOFMEMORY
;
224 VK_CALL(vkGetPhysicalDeviceQueueFamilyProperties(physical_device
, &count
, queue_properties
));
226 for (i
= 0; i
< count
; ++i
)
228 if (queue_properties
[i
].queueFlags
& VK_QUEUE_GRAPHICS_BIT
)
230 *queue_family_index
= i
;
231 *timestamp_bits
= queue_properties
[i
].timestampValidBits
;
232 heap_free(queue_properties
);
236 heap_free(queue_properties
);
238 WARN("Failed to find graphics queue.\n");
242 struct wined3d_physical_device_info
244 VkPhysicalDeviceTransformFeedbackFeaturesEXT xfb_features
;
245 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT vertex_divisor_features
;
246 VkPhysicalDeviceHostQueryResetFeatures host_query_reset_features
;
248 VkPhysicalDeviceFeatures2 features2
;
251 static void wined3d_disable_vulkan_features(struct wined3d_physical_device_info
*info
)
253 VkPhysicalDeviceFeatures
*features
= &info
->features2
.features
;
255 features
->depthBounds
= VK_FALSE
;
256 features
->wideLines
= VK_FALSE
;
257 features
->alphaToOne
= VK_FALSE
;
258 features
->textureCompressionETC2
= VK_FALSE
;
259 features
->textureCompressionASTC_LDR
= VK_FALSE
;
260 features
->shaderStorageImageMultisample
= VK_FALSE
;
261 features
->shaderUniformBufferArrayDynamicIndexing
= VK_FALSE
;
262 features
->shaderSampledImageArrayDynamicIndexing
= VK_FALSE
;
263 features
->shaderStorageBufferArrayDynamicIndexing
= VK_FALSE
;
264 features
->shaderStorageImageArrayDynamicIndexing
= VK_FALSE
;
265 features
->shaderInt64
= VK_FALSE
;
266 features
->shaderInt16
= VK_FALSE
;
267 features
->shaderResourceResidency
= VK_FALSE
;
268 features
->shaderResourceMinLod
= VK_FALSE
;
269 features
->shaderTessellationAndGeometryPointSize
= VK_FALSE
;
270 features
->sparseBinding
= VK_FALSE
;
271 features
->sparseResidencyBuffer
= VK_FALSE
;
272 features
->sparseResidencyImage2D
= VK_FALSE
;
273 features
->sparseResidencyImage3D
= VK_FALSE
;
274 features
->sparseResidency2Samples
= VK_FALSE
;
275 features
->sparseResidency4Samples
= VK_FALSE
;
276 features
->sparseResidency8Samples
= VK_FALSE
;
277 features
->sparseResidency16Samples
= VK_FALSE
;
278 features
->sparseResidencyAliased
= VK_FALSE
;
279 features
->inheritedQueries
= VK_FALSE
;
282 static struct wined3d_allocator_chunk
*wined3d_allocator_vk_create_chunk(struct wined3d_allocator
*allocator
,
283 struct wined3d_context
*context
, unsigned int memory_type
, size_t chunk_size
)
285 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
286 struct wined3d_allocator_chunk_vk
*chunk_vk
;
288 if (!(chunk_vk
= heap_alloc(sizeof(*chunk_vk
))))
291 if (!wined3d_allocator_chunk_init(&chunk_vk
->c
, allocator
))
297 if (!(chunk_vk
->vk_memory
= wined3d_context_vk_allocate_vram_chunk_memory(context_vk
, memory_type
, chunk_size
)))
299 wined3d_allocator_chunk_cleanup(&chunk_vk
->c
);
303 list_add_head(&allocator
->pools
[memory_type
].chunks
, &chunk_vk
->c
.entry
);
308 static void wined3d_allocator_vk_destroy_chunk(struct wined3d_allocator_chunk
*chunk
)
310 struct wined3d_allocator_chunk_vk
*chunk_vk
= wined3d_allocator_chunk_vk(chunk
);
311 const struct wined3d_vk_info
*vk_info
;
312 struct wined3d_device_vk
*device_vk
;
314 TRACE("chunk %p.\n", chunk
);
316 device_vk
= wined3d_device_vk_from_allocator(chunk_vk
->c
.allocator
);
317 vk_info
= &device_vk
->vk_info
;
319 if (chunk_vk
->c
.map_ptr
)
321 VK_CALL(vkUnmapMemory(device_vk
->vk_device
, chunk_vk
->vk_memory
));
322 adapter_adjust_mapped_memory(device_vk
->d
.adapter
, -WINED3D_ALLOCATOR_CHUNK_SIZE
);
324 VK_CALL(vkFreeMemory(device_vk
->vk_device
, chunk_vk
->vk_memory
, NULL
));
325 TRACE("Freed memory 0x%s.\n", wine_dbgstr_longlong(chunk_vk
->vk_memory
));
326 wined3d_allocator_chunk_cleanup(&chunk_vk
->c
);
330 static const struct wined3d_allocator_ops wined3d_allocator_vk_ops
=
332 .allocator_create_chunk
= wined3d_allocator_vk_create_chunk
,
333 .allocator_destroy_chunk
= wined3d_allocator_vk_destroy_chunk
,
336 static void get_physical_device_info(const struct wined3d_adapter_vk
*adapter_vk
, struct wined3d_physical_device_info
*info
)
338 VkPhysicalDeviceVertexAttributeDivisorFeaturesEXT
*vertex_divisor_features
= &info
->vertex_divisor_features
;
339 VkPhysicalDeviceHostQueryResetFeatures
*host_query_reset_features
= &info
->host_query_reset_features
;
340 VkPhysicalDeviceTransformFeedbackFeaturesEXT
*xfb_features
= &info
->xfb_features
;
341 VkPhysicalDevice physical_device
= adapter_vk
->physical_device
;
342 const struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
343 VkPhysicalDeviceFeatures2
*features2
= &info
->features2
;
345 memset(info
, 0, sizeof(*info
));
347 xfb_features
->sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_FEATURES_EXT
;
349 vertex_divisor_features
->sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VERTEX_ATTRIBUTE_DIVISOR_FEATURES_EXT
;
350 vertex_divisor_features
->pNext
= xfb_features
;
352 host_query_reset_features
->sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES
;
353 host_query_reset_features
->pNext
= vertex_divisor_features
;
355 features2
->sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
;
356 features2
->pNext
= host_query_reset_features
;
358 if (vk_info
->vk_ops
.vkGetPhysicalDeviceFeatures2
)
359 VK_CALL(vkGetPhysicalDeviceFeatures2(physical_device
, features2
));
361 VK_CALL(vkGetPhysicalDeviceFeatures(physical_device
, &features2
->features
));
364 static HRESULT
adapter_vk_create_device(struct wined3d
*wined3d
, const struct wined3d_adapter
*adapter
,
365 enum wined3d_device_type device_type
, HWND focus_window
, unsigned int flags
, BYTE surface_alignment
,
366 const enum wined3d_feature_level
*levels
, unsigned int level_count
,
367 struct wined3d_device_parent
*device_parent
, struct wined3d_device
**device
)
369 const struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk_const(adapter
);
370 const struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
371 struct wined3d_physical_device_info physical_device_info
;
372 static const float priorities
[] = {1.0f
};
373 struct wined3d_device_vk
*device_vk
;
374 VkDevice vk_device
= VK_NULL_HANDLE
;
375 VkDeviceQueueCreateInfo queue_info
;
376 VkPhysicalDevice physical_device
;
377 VkDeviceCreateInfo device_info
;
378 uint32_t queue_family_index
;
379 uint32_t timestamp_bits
;
383 if (!(device_vk
= heap_alloc_zero(sizeof(*device_vk
))))
384 return E_OUTOFMEMORY
;
386 if (FAILED(hr
= wined3d_select_vulkan_queue_family(adapter_vk
, &queue_family_index
, ×tamp_bits
)))
389 physical_device
= adapter_vk
->physical_device
;
391 get_physical_device_info(adapter_vk
, &physical_device_info
);
392 wined3d_disable_vulkan_features(&physical_device_info
);
394 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
;
395 queue_info
.pNext
= NULL
;
396 queue_info
.flags
= 0;
397 queue_info
.queueFamilyIndex
= queue_family_index
;
398 queue_info
.queueCount
= ARRAY_SIZE(priorities
);
399 queue_info
.pQueuePriorities
= priorities
;
401 device_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
402 device_info
.pNext
= physical_device_info
.features2
.pNext
;
403 device_info
.flags
= 0;
404 device_info
.queueCreateInfoCount
= 1;
405 device_info
.pQueueCreateInfos
= &queue_info
;
406 device_info
.enabledLayerCount
= 0;
407 device_info
.ppEnabledLayerNames
= NULL
;
408 device_info
.enabledExtensionCount
= adapter_vk
->device_extension_count
;
409 device_info
.ppEnabledExtensionNames
= adapter_vk
->device_extensions
;
410 device_info
.pEnabledFeatures
= &physical_device_info
.features2
.features
;
412 if ((vr
= VK_CALL(vkCreateDevice(physical_device
, &device_info
, NULL
, &vk_device
))) < 0)
414 WARN("Failed to create Vulkan device, vr %s.\n", wined3d_debug_vkresult(vr
));
415 vk_device
= VK_NULL_HANDLE
;
416 hr
= hresult_from_vk_result(vr
);
420 device_vk
->vk_device
= vk_device
;
421 VK_CALL(vkGetDeviceQueue(vk_device
, queue_family_index
, 0, &device_vk
->vk_queue
));
422 device_vk
->vk_queue_family_index
= queue_family_index
;
423 device_vk
->timestamp_bits
= timestamp_bits
;
425 device_vk
->vk_info
= *vk_info
;
426 #define VK_DEVICE_PFN(name) \
427 if (!(device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name)))) \
429 WARN("Could not get device proc addr for '" #name "'.\n"); \
433 #define VK_DEVICE_EXT_PFN(name) \
434 device_vk->vk_info.vk_ops.name = (void *)VK_CALL(vkGetDeviceProcAddr(vk_device, #name));
436 #undef VK_DEVICE_EXT_PFN
439 if (!wined3d_allocator_init(&device_vk
->allocator
,
440 adapter_vk
->memory_properties
.memoryTypeCount
, &wined3d_allocator_vk_ops
))
442 WARN("Failed to initialise allocator.\n");
447 if (FAILED(hr
= wined3d_device_init(&device_vk
->d
, wined3d
, adapter
->ordinal
, device_type
, focus_window
,
448 flags
, surface_alignment
, levels
, level_count
, vk_info
->supported
, device_parent
)))
450 WARN("Failed to initialize device, hr %#lx.\n", hr
);
451 wined3d_allocator_cleanup(&device_vk
->allocator
);
455 wined3d_lock_init(&device_vk
->allocator_cs
, "wined3d_device_vk.allocator_cs");
457 *device
= &device_vk
->d
;
462 VK_CALL(vkDestroyDevice(vk_device
, NULL
));
463 heap_free(device_vk
);
467 static void adapter_vk_destroy_device(struct wined3d_device
*device
)
469 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(device
);
470 const struct wined3d_vk_info
*vk_info
= &device_vk
->vk_info
;
472 wined3d_device_cleanup(&device_vk
->d
);
473 wined3d_allocator_cleanup(&device_vk
->allocator
);
475 wined3d_lock_cleanup(&device_vk
->allocator_cs
);
477 VK_CALL(vkDestroyDevice(device_vk
->vk_device
, NULL
));
478 heap_free(device_vk
);
481 static struct wined3d_context
*adapter_vk_acquire_context(struct wined3d_device
*device
,
482 struct wined3d_texture
*texture
, unsigned int sub_resource_idx
)
484 TRACE("device %p, texture %p, sub_resource_idx %u.\n", device
, texture
, sub_resource_idx
);
486 wined3d_from_cs(device
->cs
);
488 if (!device
->context_count
)
491 return &wined3d_device_vk(device
)->context_vk
.c
;
494 static void adapter_vk_release_context(struct wined3d_context
*context
)
496 TRACE("context %p.\n", context
);
499 static void adapter_vk_get_wined3d_caps(const struct wined3d_adapter
*adapter
, struct wined3d_caps
*caps
)
501 const struct wined3d_adapter_vk
*adapter_vk
= wined3d_adapter_vk_const(adapter
);
502 const VkPhysicalDeviceLimits
*limits
= &adapter_vk
->device_limits
;
503 bool sampler_anisotropy
= limits
->maxSamplerAnisotropy
> 1.0f
;
504 const struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
506 caps
->ddraw_caps
.dds_caps
|= WINEDDSCAPS_BACKBUFFER
507 | WINEDDSCAPS_COMPLEX
508 | WINEDDSCAPS_FRONTBUFFER
509 | WINEDDSCAPS_3DDEVICE
510 | WINEDDSCAPS_VIDEOMEMORY
512 | WINEDDSCAPS_LOCALVIDMEM
513 | WINEDDSCAPS_NONLOCALVIDMEM
;
514 caps
->ddraw_caps
.caps
|= WINEDDCAPS_3D
;
516 caps
->Caps2
|= WINED3DCAPS2_CANGENMIPMAP
;
518 caps
->PrimitiveMiscCaps
|= WINED3DPMISCCAPS_BLENDOP
519 | WINED3DPMISCCAPS_INDEPENDENTWRITEMASKS
520 | WINED3DPMISCCAPS_MRTINDEPENDENTBITDEPTHS
521 | WINED3DPMISCCAPS_POSTBLENDSRGBCONVERT
522 | WINED3DPMISCCAPS_SEPARATEALPHABLEND
;
524 caps
->RasterCaps
|= WINED3DPRASTERCAPS_MIPMAPLODBIAS
;
526 if (sampler_anisotropy
)
528 caps
->RasterCaps
|= WINED3DPRASTERCAPS_ANISOTROPY
;
530 caps
->TextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
531 | WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
533 caps
->MaxAnisotropy
= limits
->maxSamplerAnisotropy
;
536 caps
->SrcBlendCaps
|= WINED3DPBLENDCAPS_BLENDFACTOR
;
537 caps
->DestBlendCaps
|= WINED3DPBLENDCAPS_BLENDFACTOR
538 | WINED3DPBLENDCAPS_SRCALPHASAT
;
540 caps
->TextureCaps
|= WINED3DPTEXTURECAPS_VOLUMEMAP
541 | WINED3DPTEXTURECAPS_MIPVOLUMEMAP
542 | WINED3DPTEXTURECAPS_VOLUMEMAP_POW2
;
543 caps
->VolumeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFLINEAR
544 | WINED3DPTFILTERCAPS_MAGFPOINT
545 | WINED3DPTFILTERCAPS_MINFLINEAR
546 | WINED3DPTFILTERCAPS_MINFPOINT
547 | WINED3DPTFILTERCAPS_MIPFLINEAR
548 | WINED3DPTFILTERCAPS_MIPFPOINT
549 | WINED3DPTFILTERCAPS_LINEAR
550 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
551 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
552 | WINED3DPTFILTERCAPS_MIPLINEAR
553 | WINED3DPTFILTERCAPS_MIPNEAREST
554 | WINED3DPTFILTERCAPS_NEAREST
;
555 caps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_INDEPENDENTUV
556 | WINED3DPTADDRESSCAPS_CLAMP
557 | WINED3DPTADDRESSCAPS_WRAP
;
558 caps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
559 | WINED3DPTADDRESSCAPS_MIRROR
;
560 if (vk_info
->supported
[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE
])
561 caps
->VolumeTextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
563 caps
->MaxVolumeExtent
= limits
->maxImageDimension3D
;
565 caps
->TextureCaps
|= WINED3DPTEXTURECAPS_CUBEMAP
566 | WINED3DPTEXTURECAPS_MIPCUBEMAP
567 | WINED3DPTEXTURECAPS_CUBEMAP_POW2
;
568 caps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFLINEAR
569 | WINED3DPTFILTERCAPS_MAGFPOINT
570 | WINED3DPTFILTERCAPS_MINFLINEAR
571 | WINED3DPTFILTERCAPS_MINFPOINT
572 | WINED3DPTFILTERCAPS_MIPFLINEAR
573 | WINED3DPTFILTERCAPS_MIPFPOINT
574 | WINED3DPTFILTERCAPS_LINEAR
575 | WINED3DPTFILTERCAPS_LINEARMIPLINEAR
576 | WINED3DPTFILTERCAPS_LINEARMIPNEAREST
577 | WINED3DPTFILTERCAPS_MIPLINEAR
578 | WINED3DPTFILTERCAPS_MIPNEAREST
579 | WINED3DPTFILTERCAPS_NEAREST
;
581 if (sampler_anisotropy
)
583 caps
->CubeTextureFilterCaps
|= WINED3DPTFILTERCAPS_MAGFANISOTROPIC
584 | WINED3DPTFILTERCAPS_MINFANISOTROPIC
;
587 caps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_BORDER
588 | WINED3DPTADDRESSCAPS_MIRROR
;
589 if (vk_info
->supported
[WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE
])
590 caps
->TextureAddressCaps
|= WINED3DPTADDRESSCAPS_MIRRORONCE
;
592 caps
->StencilCaps
|= WINED3DSTENCILCAPS_DECR
593 | WINED3DSTENCILCAPS_INCR
594 | WINED3DSTENCILCAPS_TWOSIDED
;
596 caps
->DeclTypes
|= WINED3DDTCAPS_FLOAT16_2
| WINED3DDTCAPS_FLOAT16_4
;
598 caps
->MaxPixelShader30InstructionSlots
= WINED3DMAX30SHADERINSTRUCTIONS
;
599 caps
->MaxVertexShader30InstructionSlots
= WINED3DMAX30SHADERINSTRUCTIONS
;
600 caps
->PS20Caps
.temp_count
= WINED3DPS20_MAX_NUMTEMPS
;
601 caps
->VS20Caps
.temp_count
= WINED3DVS20_MAX_NUMTEMPS
;
604 static BOOL
adapter_vk_check_format(const struct wined3d_adapter
*adapter
,
605 const struct wined3d_format
*adapter_format
, const struct wined3d_format
*rt_format
,
606 const struct wined3d_format
*ds_format
)
611 static HRESULT
adapter_vk_init_3d(struct wined3d_device
*device
)
613 struct wined3d_context_vk
*context_vk
;
614 struct wined3d_device_vk
*device_vk
;
617 TRACE("device %p.\n", device
);
619 device_vk
= wined3d_device_vk(device
);
620 context_vk
= &device_vk
->context_vk
;
621 if (FAILED(hr
= wined3d_context_vk_init(context_vk
, device
->swapchains
[0])))
623 WARN("Failed to initialise context.\n");
627 if (FAILED(hr
= device
->shader_backend
->shader_alloc_private(device
,
628 device
->adapter
->vertex_pipe
, device
->adapter
->fragment_pipe
)))
630 ERR("Failed to allocate shader private data, hr %#lx.\n", hr
);
631 wined3d_context_vk_cleanup(context_vk
);
635 if (!device_context_add(device
, &context_vk
->c
))
637 ERR("Failed to add the newly created context to the context list.\n");
638 device
->shader_backend
->shader_free_private(device
, NULL
);
639 wined3d_context_vk_cleanup(context_vk
);
643 TRACE("Initialised context %p.\n", context_vk
);
645 if (!(device_vk
->d
.blitter
= wined3d_cpu_blitter_create()))
647 ERR("Failed to create CPU blitter.\n");
648 device_context_remove(device
, &context_vk
->c
);
649 device
->shader_backend
->shader_free_private(device
, NULL
);
650 wined3d_context_vk_cleanup(context_vk
);
653 wined3d_vk_blitter_create(&device_vk
->d
.blitter
);
655 wined3d_device_create_default_samplers(device
, &context_vk
->c
);
656 wined3d_device_vk_create_null_resources(device_vk
, context_vk
);
657 wined3d_device_vk_create_null_views(device_vk
, context_vk
);
658 if (device
->adapter
->d3d_info
.feature_level
>= WINED3D_FEATURE_LEVEL_11
)
659 wined3d_device_vk_uav_clear_state_init(device_vk
);
664 static void adapter_vk_uninit_3d_cs(void *object
)
666 struct wined3d_device_vk
*device_vk
= object
;
667 struct wined3d_context_vk
*context_vk
;
668 struct wined3d_device
*device
;
669 struct wined3d_shader
*shader
;
671 TRACE("device_vk %p.\n", device_vk
);
673 context_vk
= &device_vk
->context_vk
;
674 device
= &device_vk
->d
;
676 LIST_FOR_EACH_ENTRY(shader
, &device
->shaders
, struct wined3d_shader
, shader_list_entry
)
678 device
->shader_backend
->shader_destroy(shader
);
681 if (device
->adapter
->d3d_info
.feature_level
>= WINED3D_FEATURE_LEVEL_11
)
682 wined3d_device_vk_uav_clear_state_cleanup(device_vk
);
683 device
->blitter
->ops
->blitter_destroy(device
->blitter
, NULL
);
684 device
->shader_backend
->shader_free_private(device
, &context_vk
->c
);
685 wined3d_device_vk_destroy_null_views(device_vk
, context_vk
);
686 wined3d_device_vk_destroy_null_resources(device_vk
, context_vk
);
689 static void adapter_vk_uninit_3d(struct wined3d_device
*device
)
691 struct wined3d_context_vk
*context_vk
;
692 struct wined3d_device_vk
*device_vk
;
694 TRACE("device %p.\n", device
);
696 device_vk
= wined3d_device_vk(device
);
697 context_vk
= &device_vk
->context_vk
;
699 wined3d_device_destroy_default_samplers(device
);
700 wined3d_cs_destroy_object(device
->cs
, adapter_vk_uninit_3d_cs
, device_vk
);
701 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
703 device_context_remove(device
, &context_vk
->c
);
704 wined3d_context_vk_cleanup(context_vk
);
707 static void *wined3d_bo_vk_map(struct wined3d_bo_vk
*bo
, struct wined3d_context_vk
*context_vk
)
709 const struct wined3d_vk_info
*vk_info
;
710 struct wined3d_device_vk
*device_vk
;
711 struct wined3d_bo_slab_vk
*slab
;
715 return bo
->b
.map_ptr
;
717 vk_info
= context_vk
->vk_info
;
718 device_vk
= wined3d_device_vk(context_vk
->c
.device
);
720 if ((slab
= bo
->slab
))
722 if (!(bo
->b
.map_ptr
= wined3d_bo_slab_vk_map(slab
, context_vk
)))
724 ERR("Failed to map slab.\n");
730 struct wined3d_allocator_chunk_vk
*chunk_vk
= wined3d_allocator_chunk_vk(bo
->memory
->chunk
);
732 if (!(bo
->b
.map_ptr
= wined3d_allocator_chunk_vk_map(chunk_vk
, context_vk
)))
734 ERR("Failed to map chunk.\n");
740 if ((vr
= VK_CALL(vkMapMemory(device_vk
->vk_device
, bo
->vk_memory
, 0, VK_WHOLE_SIZE
, 0, &bo
->b
.map_ptr
))) < 0)
742 ERR("Failed to map memory, vr %s.\n", wined3d_debug_vkresult(vr
));
746 adapter_adjust_mapped_memory(device_vk
->d
.adapter
, bo
->size
);
749 return bo
->b
.map_ptr
;
752 static void wined3d_bo_vk_unmap(struct wined3d_bo_vk
*bo
, struct wined3d_context_vk
*context_vk
)
754 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
755 const struct wined3d_vk_info
*vk_info
;
756 struct wined3d_bo_slab_vk
*slab
;
758 /* This may race with the client thread, but it's not a hard limit anyway. */
759 if (device_vk
->d
.adapter
->mapped_size
<= MAX_PERSISTENT_MAPPED_BYTES
)
761 TRACE("Not unmapping BO %p.\n", bo
);
765 wined3d_device_bo_map_lock(context_vk
->c
.device
);
766 /* The mapping is still in use by the client (viz. for an accelerated
767 * NOOVERWRITE map). The client will trigger another unmap request when the
768 * d3d application requests to unmap the BO. */
769 if (bo
->b
.client_map_count
)
771 wined3d_device_bo_map_unlock(context_vk
->c
.device
);
772 TRACE("BO %p is still in use by a client thread; not unmapping.\n", bo
);
775 bo
->b
.map_ptr
= NULL
;
776 wined3d_device_bo_map_unlock(context_vk
->c
.device
);
778 if ((slab
= bo
->slab
))
780 wined3d_bo_slab_vk_unmap(slab
, context_vk
);
786 wined3d_allocator_chunk_vk_unmap(wined3d_allocator_chunk_vk(bo
->memory
->chunk
), context_vk
);
790 vk_info
= context_vk
->vk_info
;
791 VK_CALL(vkUnmapMemory(device_vk
->vk_device
, bo
->vk_memory
));
792 adapter_adjust_mapped_memory(device_vk
->d
.adapter
, -bo
->size
);
795 static void wined3d_bo_slab_vk_lock(struct wined3d_bo_slab_vk
*slab_vk
, struct wined3d_context_vk
*context_vk
)
797 wined3d_device_vk_allocator_lock(wined3d_device_vk(context_vk
->c
.device
));
800 static void wined3d_bo_slab_vk_unlock(struct wined3d_bo_slab_vk
*slab_vk
, struct wined3d_context_vk
*context_vk
)
802 wined3d_device_vk_allocator_unlock(wined3d_device_vk(context_vk
->c
.device
));
805 void *wined3d_bo_slab_vk_map(struct wined3d_bo_slab_vk
*slab_vk
, struct wined3d_context_vk
*context_vk
)
809 TRACE("slab_vk %p, context_vk %p.\n", slab_vk
, context_vk
);
811 wined3d_bo_slab_vk_lock(slab_vk
, context_vk
);
813 if (!slab_vk
->map_ptr
&& !(slab_vk
->map_ptr
= wined3d_bo_vk_map(&slab_vk
->bo
, context_vk
)))
815 wined3d_bo_slab_vk_unlock(slab_vk
, context_vk
);
816 ERR("Failed to map slab.\n");
820 ++slab_vk
->map_count
;
821 map_ptr
= slab_vk
->map_ptr
;
823 wined3d_bo_slab_vk_unlock(slab_vk
, context_vk
);
828 void wined3d_bo_slab_vk_unmap(struct wined3d_bo_slab_vk
*slab_vk
, struct wined3d_context_vk
*context_vk
)
830 wined3d_bo_slab_vk_lock(slab_vk
, context_vk
);
832 if (--slab_vk
->map_count
)
834 wined3d_bo_slab_vk_unlock(slab_vk
, context_vk
);
838 wined3d_bo_vk_unmap(&slab_vk
->bo
, context_vk
);
839 slab_vk
->map_ptr
= NULL
;
841 wined3d_bo_slab_vk_unlock(slab_vk
, context_vk
);
844 VkAccessFlags
vk_access_mask_from_buffer_usage(VkBufferUsageFlags usage
)
846 VkAccessFlags flags
= 0;
848 if (usage
& VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
)
849 flags
|= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT
;
850 if (usage
& VK_BUFFER_USAGE_INDEX_BUFFER_BIT
)
851 flags
|= VK_ACCESS_INDEX_READ_BIT
;
852 if (usage
& VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
)
853 flags
|= VK_ACCESS_UNIFORM_READ_BIT
;
854 if (usage
& VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
)
855 flags
|= VK_ACCESS_SHADER_READ_BIT
;
856 if (usage
& VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
)
857 flags
|= VK_ACCESS_SHADER_READ_BIT
| VK_ACCESS_SHADER_WRITE_BIT
;
858 if (usage
& VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
)
859 flags
|= VK_ACCESS_INDIRECT_COMMAND_READ_BIT
;
860 if (usage
& VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
)
861 flags
|= VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT
;
862 if (usage
& VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
)
863 flags
|= VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT
864 | VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT
;
865 if (usage
& VK_BUFFER_USAGE_TRANSFER_SRC_BIT
)
866 flags
|= VK_ACCESS_TRANSFER_READ_BIT
;
867 if (usage
& VK_BUFFER_USAGE_TRANSFER_DST_BIT
)
868 flags
|= VK_ACCESS_TRANSFER_WRITE_BIT
;
873 VkPipelineStageFlags
vk_pipeline_stage_mask_from_buffer_usage(VkBufferUsageFlags usage
)
875 VkPipelineStageFlags flags
= 0;
877 if (usage
& (VK_BUFFER_USAGE_VERTEX_BUFFER_BIT
| VK_BUFFER_USAGE_INDEX_BUFFER_BIT
))
878 flags
|= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT
;
879 if (usage
& (VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT
| VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT
880 | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT
))
881 flags
|= VK_PIPELINE_STAGE_VERTEX_SHADER_BIT
| VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT
882 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
| VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT
883 | VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT
884 | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT
;
885 if (usage
& VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT
)
886 flags
|= VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT
;
887 if (usage
& (VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT
888 | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
))
889 flags
|= VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT
;
890 if (usage
& (VK_BUFFER_USAGE_TRANSFER_SRC_BIT
| VK_BUFFER_USAGE_TRANSFER_DST_BIT
))
891 flags
|= VK_PIPELINE_STAGE_TRANSFER_BIT
;
896 static void *adapter_vk_map_bo_address(struct wined3d_context
*context
,
897 const struct wined3d_bo_address
*data
, size_t size
, uint32_t map_flags
)
899 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
900 const struct wined3d_vk_info
*vk_info
;
901 struct wined3d_device_vk
*device_vk
;
902 VkCommandBuffer vk_command_buffer
;
903 VkBufferMemoryBarrier vk_barrier
;
904 struct wined3d_bo_user
*bo_user
;
905 struct wined3d_bo_vk
*bo
, tmp
;
906 VkMappedMemoryRange range
;
909 if (!data
->buffer_object
)
911 bo
= wined3d_bo_vk(data
->buffer_object
);
913 vk_info
= context_vk
->vk_info
;
914 device_vk
= wined3d_device_vk(context
->device
);
916 if (map_flags
& WINED3D_MAP_NOOVERWRITE
)
919 if ((map_flags
& WINED3D_MAP_DISCARD
) && bo
->command_buffer_id
> context_vk
->completed_command_buffer_id
)
921 if (wined3d_context_vk_create_bo(context_vk
, bo
->size
, bo
->usage
, bo
->memory_type
, &tmp
))
923 bool host_synced
= bo
->host_synced
;
924 list_move_head(&tmp
.b
.users
, &bo
->b
.users
);
925 wined3d_context_vk_destroy_bo(context_vk
, bo
);
927 bo
->host_synced
= host_synced
;
928 list_init(&bo
->b
.users
);
929 list_move_head(&bo
->b
.users
, &tmp
.b
.users
);
930 LIST_FOR_EACH_ENTRY(bo_user
, &bo
->b
.users
, struct wined3d_bo_user
, entry
)
932 bo_user
->valid
= false;
938 ERR("Failed to create new buffer object.\n");
941 if (map_flags
& WINED3D_MAP_READ
)
943 if (!bo
->host_synced
)
945 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
947 ERR("Failed to get command buffer.\n");
951 wined3d_context_vk_end_current_render_pass(context_vk
);
953 vk_barrier
.sType
= VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
;
954 vk_barrier
.pNext
= NULL
;
955 vk_barrier
.srcAccessMask
= vk_access_mask_from_buffer_usage(bo
->usage
);
956 vk_barrier
.dstAccessMask
= VK_ACCESS_HOST_READ_BIT
;
957 vk_barrier
.srcQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
958 vk_barrier
.dstQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
959 vk_barrier
.buffer
= bo
->vk_buffer
;
960 vk_barrier
.offset
= bo
->b
.buffer_offset
+ (uintptr_t)data
->addr
;
961 vk_barrier
.size
= size
;
962 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
963 VK_PIPELINE_STAGE_HOST_BIT
, 0, 0, NULL
, 1, &vk_barrier
, 0, NULL
));
965 wined3d_context_vk_reference_bo(context_vk
, bo
);
970 range
.sType
= VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
;
972 range
.memory
= bo
->vk_memory
;
973 range
.offset
= bo
->b
.memory_offset
+ (uintptr_t)data
->addr
;
975 VK_CALL(vkInvalidateMappedMemoryRanges(device_vk
->vk_device
, 1, &range
));
979 if (bo
->command_buffer_id
== context_vk
->current_command_buffer
.id
)
980 wined3d_context_vk_submit_command_buffer(context_vk
, 0, NULL
, NULL
, 0, NULL
);
981 wined3d_context_vk_wait_command_buffer(context_vk
, bo
->command_buffer_id
);
984 if (!(map_ptr
= wined3d_bo_vk_map(bo
, context_vk
)))
986 ERR("Failed to map bo.\n");
990 return (uint8_t *)map_ptr
+ bo
->b
.memory_offset
+ (uintptr_t)data
->addr
;
993 static void flush_bo_range(struct wined3d_context_vk
*context_vk
,
994 struct wined3d_bo_vk
*bo
, unsigned int offset
, unsigned int size
)
996 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(context_vk
->c
.device
);
997 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
998 VkMappedMemoryRange range
;
1000 range
.sType
= VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE
;
1002 range
.memory
= bo
->vk_memory
;
1003 range
.offset
= bo
->b
.memory_offset
+ offset
;
1005 VK_CALL(vkFlushMappedMemoryRanges(device_vk
->vk_device
, 1, &range
));
1008 static void adapter_vk_unmap_bo_address(struct wined3d_context
*context
,
1009 const struct wined3d_bo_address
*data
, unsigned int range_count
, const struct wined3d_range
*ranges
)
1011 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
1012 struct wined3d_bo_vk
*bo
;
1015 if (!data
->buffer_object
)
1017 bo
= wined3d_bo_vk(data
->buffer_object
);
1019 assert(bo
->b
.map_ptr
);
1021 if (!bo
->b
.coherent
)
1023 for (i
= 0; i
< range_count
; ++i
)
1024 flush_bo_range(context_vk
, bo
, ranges
[i
].offset
, ranges
[i
].size
);
1027 wined3d_bo_vk_unmap(bo
, context_vk
);
1030 void adapter_vk_copy_bo_address(struct wined3d_context
*context
,
1031 const struct wined3d_bo_address
*dst
, const struct wined3d_bo_address
*src
,
1032 unsigned int range_count
, const struct wined3d_range
*ranges
, uint32_t map_flags
)
1034 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
1035 const struct wined3d_vk_info
*vk_info
= context_vk
->vk_info
;
1036 struct wined3d_bo_vk staging_bo
, *src_bo
, *dst_bo
;
1037 VkAccessFlags src_access_mask
, dst_access_mask
;
1038 VkBufferMemoryBarrier vk_barrier
[2];
1039 const struct wined3d_range
*range
;
1040 struct wined3d_bo_address staging
;
1041 VkCommandBuffer vk_command_buffer
;
1042 uint8_t *dst_ptr
, *src_ptr
;
1043 VkBufferCopy region
;
1047 src_bo
= src
->buffer_object
? wined3d_bo_vk(src
->buffer_object
) : NULL
;
1048 dst_bo
= dst
->buffer_object
? wined3d_bo_vk(dst
->buffer_object
) : NULL
;
1050 if (src_bo
&& dst_bo
)
1052 if (!(vk_command_buffer
= wined3d_context_vk_get_command_buffer(context_vk
)))
1054 ERR("Failed to get command buffer.\n");
1058 wined3d_context_vk_end_current_render_pass(context_vk
);
1060 src_access_mask
= vk_access_mask_from_buffer_usage(src_bo
->usage
);
1061 dst_access_mask
= vk_access_mask_from_buffer_usage(dst_bo
->usage
);
1063 vk_barrier
[0].sType
= VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
;
1064 vk_barrier
[0].pNext
= NULL
;
1065 vk_barrier
[0].srcQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1066 vk_barrier
[0].dstQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1067 vk_barrier
[0].buffer
= src_bo
->vk_buffer
;
1069 vk_barrier
[1].sType
= VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER
;
1070 vk_barrier
[1].pNext
= NULL
;
1071 vk_barrier
[1].srcQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1072 vk_barrier
[1].dstQueueFamilyIndex
= VK_QUEUE_FAMILY_IGNORED
;
1073 vk_barrier
[1].buffer
= dst_bo
->vk_buffer
;
1075 for (i
= 0; i
< range_count
; ++i
)
1079 region
.srcOffset
= src_bo
->b
.buffer_offset
+ (uintptr_t)src
->addr
+ range
->offset
;
1080 region
.dstOffset
= dst_bo
->b
.buffer_offset
+ (uintptr_t)dst
->addr
+ range
->offset
;
1081 region
.size
= range
->size
;
1083 vk_barrier
[0].offset
= region
.srcOffset
;
1084 vk_barrier
[0].size
= region
.size
;
1086 vk_barrier
[1].offset
= region
.dstOffset
;
1087 vk_barrier
[1].size
= region
.size
;
1089 vk_barrier
[0].srcAccessMask
= src_access_mask
;
1090 vk_barrier
[0].dstAccessMask
= VK_ACCESS_TRANSFER_READ_BIT
;
1092 vk_barrier
[1].srcAccessMask
= dst_access_mask
;
1093 vk_barrier
[1].dstAccessMask
= VK_ACCESS_TRANSFER_WRITE_BIT
;
1095 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
,
1096 VK_PIPELINE_STAGE_TRANSFER_BIT
, 0, 0, NULL
, 2, vk_barrier
, 0, NULL
));
1098 VK_CALL(vkCmdCopyBuffer(vk_command_buffer
, src_bo
->vk_buffer
, dst_bo
->vk_buffer
, 1, ®ion
));
1100 vk_barrier
[0].srcAccessMask
= VK_ACCESS_TRANSFER_READ_BIT
;
1101 vk_barrier
[0].dstAccessMask
= src_access_mask
;
1103 vk_barrier
[1].srcAccessMask
= VK_ACCESS_TRANSFER_WRITE_BIT
;
1104 vk_barrier
[1].dstAccessMask
= dst_access_mask
;
1106 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, VK_PIPELINE_STAGE_TRANSFER_BIT
,
1107 VK_PIPELINE_STAGE_ALL_COMMANDS_BIT
, 0, 0, NULL
, 2, vk_barrier
, 0, NULL
));
1110 wined3d_context_vk_reference_bo(context_vk
, src_bo
);
1111 wined3d_context_vk_reference_bo(context_vk
, dst_bo
);
1116 for (i
= 0; i
< range_count
; ++i
)
1117 size
= max(size
, ranges
[i
].offset
+ ranges
[i
].size
);
1119 if (src_bo
&& !(src_bo
->memory_type
& VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
))
1121 if (!(wined3d_context_vk_create_bo(context_vk
, size
, VK_BUFFER_USAGE_TRANSFER_DST_BIT
,
1122 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
)))
1124 ERR("Failed to create staging bo.\n");
1128 staging
.buffer_object
= &staging_bo
.b
;
1129 staging
.addr
= NULL
;
1130 adapter_vk_copy_bo_address(context
, &staging
, src
, range_count
, ranges
, WINED3D_MAP_WRITE
);
1131 adapter_vk_copy_bo_address(context
, dst
, &staging
, range_count
, ranges
, WINED3D_MAP_WRITE
);
1133 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
1138 if (dst_bo
&& (!(dst_bo
->memory_type
& VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
) || (!(map_flags
& WINED3D_MAP_DISCARD
)
1139 && dst_bo
->command_buffer_id
> context_vk
->completed_command_buffer_id
)))
1141 if (!(wined3d_context_vk_create_bo(context_vk
, size
, VK_BUFFER_USAGE_TRANSFER_SRC_BIT
,
1142 VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, &staging_bo
)))
1144 ERR("Failed to create staging bo.\n");
1148 staging
.buffer_object
= &staging_bo
.b
;
1149 staging
.addr
= NULL
;
1150 adapter_vk_copy_bo_address(context
, &staging
, src
, range_count
, ranges
, WINED3D_MAP_WRITE
);
1151 adapter_vk_copy_bo_address(context
, dst
, &staging
, range_count
, ranges
, WINED3D_MAP_WRITE
);
1153 wined3d_context_vk_destroy_bo(context_vk
, &staging_bo
);
1158 src_ptr
= adapter_vk_map_bo_address(context
, src
, size
, WINED3D_MAP_READ
);
1159 dst_ptr
= adapter_vk_map_bo_address(context
, dst
, size
, map_flags
);
1161 for (i
= 0; i
< range_count
; ++i
)
1162 memcpy(dst_ptr
+ ranges
[i
].offset
, src_ptr
+ ranges
[i
].offset
, ranges
[i
].size
);
1164 adapter_vk_unmap_bo_address(context
, dst
, range_count
, ranges
);
1165 adapter_vk_unmap_bo_address(context
, src
, 0, NULL
);
1168 static void adapter_vk_flush_bo_address(struct wined3d_context
*context
,
1169 const struct wined3d_const_bo_address
*data
, size_t size
)
1171 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
1172 struct wined3d_bo
*bo
;
1174 if (!(bo
= data
->buffer_object
))
1177 flush_bo_range(context_vk
, wined3d_bo_vk(bo
), (uintptr_t)data
->addr
, size
);
1180 static bool adapter_vk_alloc_bo(struct wined3d_device
*device
, struct wined3d_resource
*resource
,
1181 unsigned int sub_resource_idx
, struct wined3d_bo_address
*addr
)
1183 struct wined3d_device_vk
*device_vk
= wined3d_device_vk(device
);
1184 struct wined3d_context_vk
*context_vk
= &device_vk
->context_vk
;
1185 VkMemoryPropertyFlags memory_type
;
1186 VkBufferUsageFlags buffer_usage
;
1187 struct wined3d_bo_vk
*bo_vk
;
1190 wined3d_not_from_cs(device
->cs
);
1191 assert(device
->context_count
);
1193 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
1195 buffer_usage
= vk_buffer_usage_from_bind_flags(resource
->bind_flags
);
1196 memory_type
= vk_memory_type_from_access_flags(resource
->access
, resource
->usage
);
1197 size
= resource
->size
;
1201 struct wined3d_texture
*texture
= texture_from_resource(resource
);
1203 buffer_usage
= VK_BUFFER_USAGE_TRANSFER_DST_BIT
| VK_BUFFER_USAGE_TRANSFER_SRC_BIT
;
1204 memory_type
= VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
;
1205 size
= texture
->sub_resources
[sub_resource_idx
].size
;
1208 if (!(bo_vk
= heap_alloc(sizeof(*bo_vk
))))
1211 if (!(wined3d_context_vk_create_bo(context_vk
, size
, buffer_usage
, memory_type
, bo_vk
)))
1213 WARN("Failed to create Vulkan buffer.\n");
1218 if (!bo_vk
->b
.map_ptr
)
1220 if (!wined3d_bo_vk_map(bo_vk
, context_vk
))
1221 ERR("Failed to map bo.\n");
1224 addr
->buffer_object
= &bo_vk
->b
;
1229 static void adapter_vk_destroy_bo(struct wined3d_context
*context
, struct wined3d_bo
*bo
)
1231 wined3d_context_vk_destroy_bo(wined3d_context_vk(context
), wined3d_bo_vk(bo
));
1234 static HRESULT
adapter_vk_create_swapchain(struct wined3d_device
*device
,
1235 struct wined3d_swapchain_desc
*desc
, struct wined3d_swapchain_state_parent
*state_parent
,
1236 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_swapchain
**swapchain
)
1238 struct wined3d_swapchain_vk
*swapchain_vk
;
1241 TRACE("device %p, desc %p, state_parent %p, parent %p, parent_ops %p, swapchain %p.\n",
1242 device
, desc
, state_parent
, parent
, parent_ops
, swapchain
);
1244 if (!(swapchain_vk
= heap_alloc_zero(sizeof(*swapchain_vk
))))
1245 return E_OUTOFMEMORY
;
1247 if (FAILED(hr
= wined3d_swapchain_vk_init(swapchain_vk
, device
, desc
, state_parent
, parent
,
1250 WARN("Failed to initialise swapchain, hr %#lx.\n", hr
);
1251 heap_free(swapchain_vk
);
1255 TRACE("Created swapchain %p.\n", swapchain_vk
);
1256 *swapchain
= &swapchain_vk
->s
;
1261 static void adapter_vk_destroy_swapchain(struct wined3d_swapchain
*swapchain
)
1263 struct wined3d_swapchain_vk
*swapchain_vk
= wined3d_swapchain_vk(swapchain
);
1265 wined3d_swapchain_vk_cleanup(swapchain_vk
);
1266 heap_free(swapchain_vk
);
1269 unsigned int wined3d_adapter_vk_get_memory_type_index(const struct wined3d_adapter_vk
*adapter_vk
,
1270 uint32_t memory_type_mask
, VkMemoryPropertyFlags flags
)
1272 const VkPhysicalDeviceMemoryProperties
*memory_info
= &adapter_vk
->memory_properties
;
1275 for (i
= 0; i
< memory_info
->memoryTypeCount
; ++i
)
1277 if (!(memory_type_mask
& (1u << i
)))
1279 if ((memory_info
->memoryTypes
[i
].propertyFlags
& flags
) == flags
)
1286 static HRESULT
adapter_vk_create_buffer(struct wined3d_device
*device
,
1287 const struct wined3d_buffer_desc
*desc
, const struct wined3d_sub_resource_data
*data
,
1288 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_buffer
**buffer
)
1290 struct wined3d_buffer_vk
*buffer_vk
;
1293 TRACE("device %p, desc %p, data %p, parent %p, parent_ops %p, buffer %p.\n",
1294 device
, desc
, data
, parent
, parent_ops
, buffer
);
1296 if (!(buffer_vk
= heap_alloc_zero(sizeof(*buffer_vk
))))
1297 return E_OUTOFMEMORY
;
1299 if (FAILED(hr
= wined3d_buffer_vk_init(buffer_vk
, device
, desc
, data
, parent
, parent_ops
)))
1301 WARN("Failed to initialise buffer, hr %#lx.\n", hr
);
1302 heap_free(buffer_vk
);
1306 TRACE("Created buffer %p.\n", buffer_vk
);
1307 *buffer
= &buffer_vk
->b
;
1312 static void adapter_vk_destroy_buffer(struct wined3d_buffer
*buffer
)
1314 struct wined3d_buffer_vk
*buffer_vk
= wined3d_buffer_vk(buffer
);
1315 struct wined3d_device
*device
= buffer_vk
->b
.resource
.device
;
1316 unsigned int swapchain_count
= device
->swapchain_count
;
1318 TRACE("buffer_vk %p.\n", buffer_vk
);
1320 /* Take a reference to the device, in case releasing the buffer would
1321 * cause the device to be destroyed. However, swapchain resources don't
1322 * take a reference to the device, and we wouldn't want to increment the
1323 * refcount on a device that's in the process of being destroyed. */
1324 if (swapchain_count
)
1325 wined3d_device_incref(device
);
1326 wined3d_buffer_cleanup(&buffer_vk
->b
);
1327 wined3d_cs_destroy_object(device
->cs
, heap_free
, buffer_vk
);
1328 if (swapchain_count
)
1329 wined3d_device_decref(device
);
1332 static HRESULT
adapter_vk_create_texture(struct wined3d_device
*device
,
1333 const struct wined3d_resource_desc
*desc
, unsigned int layer_count
, unsigned int level_count
,
1334 uint32_t flags
, void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_texture
**texture
)
1336 struct wined3d_texture_vk
*texture_vk
;
1339 TRACE("device %p, desc %p, layer_count %u, level_count %u, flags %#x, parent %p, parent_ops %p, texture %p.\n",
1340 device
, desc
, layer_count
, level_count
, flags
, parent
, parent_ops
, texture
);
1342 if (!(texture_vk
= wined3d_texture_allocate_object_memory(sizeof(*texture_vk
), level_count
, layer_count
)))
1343 return E_OUTOFMEMORY
;
1345 if (FAILED(hr
= wined3d_texture_vk_init(texture_vk
, device
, desc
,
1346 layer_count
, level_count
, flags
, parent
, parent_ops
)))
1348 WARN("Failed to initialise texture, hr %#lx.\n", hr
);
1349 heap_free(texture_vk
);
1353 TRACE("Created texture %p.\n", texture_vk
);
1354 *texture
= &texture_vk
->t
;
1359 static void adapter_vk_destroy_texture(struct wined3d_texture
*texture
)
1361 struct wined3d_texture_vk
*texture_vk
= wined3d_texture_vk(texture
);
1362 struct wined3d_device
*device
= texture_vk
->t
.resource
.device
;
1363 unsigned int swapchain_count
= device
->swapchain_count
;
1365 TRACE("texture_vk %p.\n", texture_vk
);
1367 /* Take a reference to the device, in case releasing the texture would
1368 * cause the device to be destroyed. However, swapchain resources don't
1369 * take a reference to the device, and we wouldn't want to increment the
1370 * refcount on a device that's in the process of being destroyed. */
1371 if (swapchain_count
)
1372 wined3d_device_incref(device
);
1374 wined3d_texture_sub_resources_destroyed(texture
);
1375 texture
->resource
.parent_ops
->wined3d_object_destroyed(texture
->resource
.parent
);
1377 wined3d_texture_cleanup(&texture_vk
->t
);
1378 wined3d_cs_destroy_object(device
->cs
, heap_free
, texture_vk
);
1380 if (swapchain_count
)
1381 wined3d_device_decref(device
);
1384 static HRESULT
adapter_vk_create_rendertarget_view(const struct wined3d_view_desc
*desc
,
1385 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1386 struct wined3d_rendertarget_view
**view
)
1388 struct wined3d_rendertarget_view_vk
*view_vk
;
1391 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1392 wined3d_debug_view_desc(desc
, resource
), resource
, parent
, parent_ops
, view
);
1394 if (!(view_vk
= heap_alloc_zero(sizeof(*view_vk
))))
1395 return E_OUTOFMEMORY
;
1397 if (FAILED(hr
= wined3d_rendertarget_view_vk_init(view_vk
, desc
, resource
, parent
, parent_ops
)))
1399 WARN("Failed to initialise view, hr %#lx.\n", hr
);
1404 TRACE("Created render target view %p.\n", view_vk
);
1405 *view
= &view_vk
->v
;
1410 struct wined3d_view_vk_destroy_ctx
1412 struct wined3d_device_vk
*device_vk
;
1413 VkBufferView
*vk_buffer_view
;
1414 VkImageView
*vk_image_view
;
1415 struct wined3d_bo_user
*bo_user
;
1416 struct wined3d_bo_vk
*vk_counter_bo
;
1417 VkBufferView
*vk_counter_view
;
1418 uint64_t *command_buffer_id
;
1420 struct wined3d_view_vk_destroy_ctx
*free
;
1423 static void wined3d_view_vk_destroy_object(void *object
)
1425 struct wined3d_view_vk_destroy_ctx
*ctx
= object
;
1426 const struct wined3d_vk_info
*vk_info
;
1427 struct wined3d_device_vk
*device_vk
;
1428 struct wined3d_context
*context
;
1430 TRACE("ctx %p.\n", ctx
);
1432 device_vk
= ctx
->device_vk
;
1433 vk_info
= &wined3d_adapter_vk(device_vk
->d
.adapter
)->vk_info
;
1434 context
= context_acquire(&device_vk
->d
, NULL
, 0);
1436 if (ctx
->vk_buffer_view
)
1440 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context
),
1441 *ctx
->vk_buffer_view
, *ctx
->command_buffer_id
);
1445 VK_CALL(vkDestroyBufferView(device_vk
->vk_device
, *ctx
->vk_buffer_view
, NULL
));
1446 TRACE("Destroyed buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx
->vk_buffer_view
));
1449 if (ctx
->vk_image_view
)
1453 wined3d_context_vk_destroy_vk_image_view(wined3d_context_vk(context
),
1454 *ctx
->vk_image_view
, *ctx
->command_buffer_id
);
1458 VK_CALL(vkDestroyImageView(device_vk
->vk_device
, *ctx
->vk_image_view
, NULL
));
1459 TRACE("Destroyed image view 0x%s.\n", wine_dbgstr_longlong(*ctx
->vk_image_view
));
1463 list_remove(&ctx
->bo_user
->entry
);
1464 if (ctx
->vk_counter_bo
&& ctx
->vk_counter_bo
->vk_buffer
)
1465 wined3d_context_vk_destroy_bo(wined3d_context_vk(context
), ctx
->vk_counter_bo
);
1466 if (ctx
->vk_counter_view
)
1470 wined3d_context_vk_destroy_vk_buffer_view(wined3d_context_vk(context
),
1471 *ctx
->vk_counter_view
, *ctx
->command_buffer_id
);
1475 VK_CALL(vkDestroyBufferView(device_vk
->vk_device
, *ctx
->vk_counter_view
, NULL
));
1476 TRACE("Destroyed counter buffer view 0x%s.\n", wine_dbgstr_longlong(*ctx
->vk_counter_view
));
1481 context_release(context
);
1483 heap_free(ctx
->object
);
1484 heap_free(ctx
->free
);
1487 static void wined3d_view_vk_destroy(struct wined3d_device
*device
, VkBufferView
*vk_buffer_view
,
1488 VkImageView
*vk_image_view
, struct wined3d_bo_user
*bo_user
, struct wined3d_bo_vk
*vk_counter_bo
,
1489 VkBufferView
*vk_counter_view
, uint64_t *command_buffer_id
, void *view_vk
)
1491 struct wined3d_view_vk_destroy_ctx
*ctx
, c
;
1493 if (!(ctx
= heap_alloc(sizeof(*ctx
))))
1495 ctx
->device_vk
= wined3d_device_vk(device
);
1496 ctx
->vk_buffer_view
= vk_buffer_view
;
1497 ctx
->vk_image_view
= vk_image_view
;
1498 ctx
->bo_user
= bo_user
;
1499 ctx
->vk_counter_bo
= vk_counter_bo
;
1500 ctx
->vk_counter_view
= vk_counter_view
;
1501 ctx
->command_buffer_id
= command_buffer_id
;
1502 ctx
->object
= view_vk
;
1503 ctx
->free
= ctx
!= &c
? ctx
: NULL
;
1505 wined3d_cs_destroy_object(device
->cs
, wined3d_view_vk_destroy_object
, ctx
);
1507 wined3d_cs_finish(device
->cs
, WINED3D_CS_QUEUE_DEFAULT
);
1510 static void adapter_vk_destroy_rendertarget_view(struct wined3d_rendertarget_view
*view
)
1512 struct wined3d_rendertarget_view_vk
*view_vk
= wined3d_rendertarget_view_vk(view
);
1513 struct wined3d_resource
*resource
= view_vk
->v
.resource
;
1515 TRACE("view_vk %p.\n", view_vk
);
1517 /* Take a reference to the resource, in case releasing the resource
1518 * would cause the device to be destroyed. */
1519 wined3d_resource_incref(resource
);
1520 wined3d_rendertarget_view_cleanup(&view_vk
->v
);
1521 wined3d_view_vk_destroy(resource
->device
, NULL
, &view_vk
->vk_image_view
,
1522 NULL
, NULL
, NULL
, &view_vk
->command_buffer_id
, view_vk
);
1523 wined3d_resource_decref(resource
);
1526 static HRESULT
adapter_vk_create_shader_resource_view(const struct wined3d_view_desc
*desc
,
1527 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1528 struct wined3d_shader_resource_view
**view
)
1530 struct wined3d_shader_resource_view_vk
*view_vk
;
1533 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1534 wined3d_debug_view_desc(desc
, resource
), resource
, parent
, parent_ops
, view
);
1536 if (!(view_vk
= heap_alloc_zero(sizeof(*view_vk
))))
1537 return E_OUTOFMEMORY
;
1539 if (FAILED(hr
= wined3d_shader_resource_view_vk_init(view_vk
, desc
, resource
, parent
, parent_ops
)))
1541 WARN("Failed to initialise view, hr %#lx.\n", hr
);
1546 TRACE("Created shader resource view %p.\n", view_vk
);
1547 *view
= &view_vk
->v
;
1552 static void adapter_vk_destroy_shader_resource_view(struct wined3d_shader_resource_view
*view
)
1554 struct wined3d_shader_resource_view_vk
*srv_vk
= wined3d_shader_resource_view_vk(view
);
1555 struct wined3d_resource
*resource
= srv_vk
->v
.resource
;
1556 struct wined3d_view_vk
*view_vk
= &srv_vk
->view_vk
;
1557 VkBufferView
*vk_buffer_view
= NULL
;
1558 VkImageView
*vk_image_view
= NULL
;
1560 TRACE("srv_vk %p.\n", srv_vk
);
1562 /* Take a reference to the resource. There are two reasons for this:
1563 * - Releasing the resource could in turn cause the device to be
1564 * destroyed, but we still need the device for
1565 * wined3d_view_vk_destroy().
1566 * - We shouldn't free buffer resources until after we've removed the
1567 * view from its bo_user list. */
1568 wined3d_resource_incref(resource
);
1569 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
1570 vk_buffer_view
= &view_vk
->u
.vk_buffer_view
;
1572 vk_image_view
= &view_vk
->u
.vk_image_info
.imageView
;
1573 wined3d_shader_resource_view_cleanup(&srv_vk
->v
);
1574 wined3d_view_vk_destroy(resource
->device
, vk_buffer_view
, vk_image_view
,
1575 &view_vk
->bo_user
, NULL
, NULL
, &view_vk
->command_buffer_id
, srv_vk
);
1576 wined3d_resource_decref(resource
);
1579 static HRESULT
adapter_vk_create_unordered_access_view(const struct wined3d_view_desc
*desc
,
1580 struct wined3d_resource
*resource
, void *parent
, const struct wined3d_parent_ops
*parent_ops
,
1581 struct wined3d_unordered_access_view
**view
)
1583 struct wined3d_unordered_access_view_vk
*view_vk
;
1586 TRACE("desc %s, resource %p, parent %p, parent_ops %p, view %p.\n",
1587 wined3d_debug_view_desc(desc
, resource
), resource
, parent
, parent_ops
, view
);
1589 if (!(view_vk
= heap_alloc_zero(sizeof(*view_vk
))))
1590 return E_OUTOFMEMORY
;
1592 if (FAILED(hr
= wined3d_unordered_access_view_vk_init(view_vk
, desc
, resource
, parent
, parent_ops
)))
1594 WARN("Failed to initialise view, hr %#lx.\n", hr
);
1599 TRACE("Created unordered access view %p.\n", view_vk
);
1600 *view
= &view_vk
->v
;
1605 static void adapter_vk_destroy_unordered_access_view(struct wined3d_unordered_access_view
*view
)
1607 struct wined3d_unordered_access_view_vk
*uav_vk
= wined3d_unordered_access_view_vk(view
);
1608 struct wined3d_resource
*resource
= uav_vk
->v
.resource
;
1609 struct wined3d_view_vk
*view_vk
= &uav_vk
->view_vk
;
1610 VkBufferView
*vk_buffer_view
= NULL
;
1611 VkImageView
*vk_image_view
= NULL
;
1613 TRACE("uav_vk %p.\n", uav_vk
);
1615 /* Take a reference to the resource. There are two reasons for this:
1616 * - Releasing the resource could in turn cause the device to be
1617 * destroyed, but we still need the device for
1618 * wined3d_view_vk_destroy().
1619 * - We shouldn't free buffer resources until after we've removed the
1620 * view from its bo_user list. */
1621 wined3d_resource_incref(resource
);
1622 if (resource
->type
== WINED3D_RTYPE_BUFFER
)
1623 vk_buffer_view
= &view_vk
->u
.vk_buffer_view
;
1625 vk_image_view
= &view_vk
->u
.vk_image_info
.imageView
;
1626 wined3d_unordered_access_view_cleanup(&uav_vk
->v
);
1627 wined3d_view_vk_destroy(resource
->device
, vk_buffer_view
, vk_image_view
, &view_vk
->bo_user
,
1628 &uav_vk
->counter_bo
, &uav_vk
->vk_counter_view
, &view_vk
->command_buffer_id
, uav_vk
);
1629 wined3d_resource_decref(resource
);
1632 static HRESULT
adapter_vk_create_sampler(struct wined3d_device
*device
, const struct wined3d_sampler_desc
*desc
,
1633 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_sampler
**sampler
)
1635 struct wined3d_sampler_vk
*sampler_vk
;
1637 TRACE("device %p, desc %p, parent %p, parent_ops %p, sampler %p.\n",
1638 device
, desc
, parent
, parent_ops
, sampler
);
1640 if (!(sampler_vk
= heap_alloc_zero(sizeof(*sampler_vk
))))
1641 return E_OUTOFMEMORY
;
1643 wined3d_sampler_vk_init(sampler_vk
, device
, desc
, parent
, parent_ops
);
1645 TRACE("Created sampler %p.\n", sampler_vk
);
1646 *sampler
= &sampler_vk
->s
;
1651 static void wined3d_sampler_vk_destroy_object(void *object
)
1653 struct wined3d_sampler_vk
*sampler_vk
= object
;
1654 struct wined3d_context_vk
*context_vk
;
1656 TRACE("sampler_vk %p.\n", sampler_vk
);
1658 context_vk
= wined3d_context_vk(context_acquire(sampler_vk
->s
.device
, NULL
, 0));
1660 wined3d_context_vk_destroy_vk_sampler(context_vk
, sampler_vk
->vk_image_info
.sampler
, sampler_vk
->command_buffer_id
);
1661 heap_free(sampler_vk
);
1663 context_release(&context_vk
->c
);
1666 static void adapter_vk_destroy_sampler(struct wined3d_sampler
*sampler
)
1668 struct wined3d_sampler_vk
*sampler_vk
= wined3d_sampler_vk(sampler
);
1670 TRACE("sampler_vk %p.\n", sampler_vk
);
1672 wined3d_cs_destroy_object(sampler
->device
->cs
, wined3d_sampler_vk_destroy_object
, sampler_vk
);
1675 static HRESULT
adapter_vk_create_query(struct wined3d_device
*device
, enum wined3d_query_type type
,
1676 void *parent
, const struct wined3d_parent_ops
*parent_ops
, struct wined3d_query
**query
)
1678 TRACE("device %p, type %#x, parent %p, parent_ops %p, query %p.\n",
1679 device
, type
, parent
, parent_ops
, query
);
1681 return wined3d_query_vk_create(device
, type
, parent
, parent_ops
, query
);
1684 static void wined3d_query_vk_destroy_object(void *object
)
1686 struct wined3d_query_vk
*query_vk
= object
;
1688 TRACE("query_vk %p.\n", query_vk
);
1690 query_vk
->q
.query_ops
->query_destroy(&query_vk
->q
);
1693 static void adapter_vk_destroy_query(struct wined3d_query
*query
)
1695 struct wined3d_query_vk
*query_vk
= wined3d_query_vk(query
);
1697 TRACE("query_vk %p.\n", query_vk
);
1699 wined3d_cs_destroy_object(query
->device
->cs
, wined3d_query_vk_destroy_object
, query_vk
);
1702 static void adapter_vk_flush_context(struct wined3d_context
*context
)
1704 struct wined3d_context_vk
*context_vk
= wined3d_context_vk(context
);
1706 TRACE("context_vk %p.\n", context_vk
);
1708 wined3d_context_vk_submit_command_buffer(context_vk
, 0, NULL
, NULL
, 0, NULL
);
1711 static void adapter_vk_draw_primitive(struct wined3d_device
*device
,
1712 const struct wined3d_state
*state
, const struct wined3d_draw_parameters
*parameters
)
1714 struct wined3d_buffer_vk
*indirect_vk
= NULL
;
1715 const struct wined3d_vk_info
*vk_info
;
1716 struct wined3d_context_vk
*context_vk
;
1717 VkCommandBuffer vk_command_buffer
;
1718 uint32_t instance_count
;
1721 TRACE("device %p, state %p, parameters %p.\n", device
, state
, parameters
);
1723 context_vk
= wined3d_context_vk(context_acquire(device
, NULL
, 0));
1724 vk_info
= context_vk
->vk_info
;
1726 if (parameters
->indirect
)
1727 indirect_vk
= wined3d_buffer_vk(parameters
->u
.indirect
.buffer
);
1729 if (!(vk_command_buffer
= wined3d_context_vk_apply_draw_state(context_vk
,
1730 state
, indirect_vk
, parameters
->indexed
)))
1732 ERR("Failed to apply draw state.\n");
1733 context_release(&context_vk
->c
);
1737 if (context_vk
->c
.transform_feedback_active
)
1739 if (!context_vk
->vk_so_counter_bo
.vk_buffer
)
1741 struct wined3d_bo_vk
*bo
= &context_vk
->vk_so_counter_bo
;
1743 if (!wined3d_context_vk_create_bo(context_vk
, ARRAY_SIZE(context_vk
->vk_so_counters
) * sizeof(uint32_t) * 2,
1744 VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT
, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
, bo
))
1745 ERR("Failed to create counter BO.\n");
1746 for (i
= 0; i
< ARRAY_SIZE(context_vk
->vk_so_counters
); ++i
)
1748 context_vk
->vk_so_counters
[i
] = bo
->vk_buffer
;
1749 context_vk
->vk_so_offsets
[i
] = bo
->b
.buffer_offset
+ i
* sizeof(uint32_t) * 2;
1753 wined3d_context_vk_reference_bo(context_vk
, &context_vk
->vk_so_counter_bo
);
1754 if (context_vk
->c
.transform_feedback_paused
)
1755 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer
, 0, ARRAY_SIZE(context_vk
->vk_so_counters
),
1756 context_vk
->vk_so_counters
, context_vk
->vk_so_offsets
));
1758 VK_CALL(vkCmdBeginTransformFeedbackEXT(vk_command_buffer
, 0, 0, NULL
, NULL
));
1761 if (parameters
->indirect
)
1763 struct wined3d_bo_vk
*bo
= wined3d_bo_vk(indirect_vk
->b
.buffer_object
);
1765 wined3d_context_vk_reference_bo(context_vk
, bo
);
1766 if (parameters
->indexed
)
1767 VK_CALL(vkCmdDrawIndexedIndirect(vk_command_buffer
, bo
->vk_buffer
,
1768 bo
->b
.buffer_offset
+ parameters
->u
.indirect
.offset
, 1, sizeof(VkDrawIndexedIndirectCommand
)));
1770 VK_CALL(vkCmdDrawIndirect(vk_command_buffer
, bo
->vk_buffer
,
1771 bo
->b
.buffer_offset
+ parameters
->u
.indirect
.offset
, 1, sizeof(VkDrawIndirectCommand
)));
1775 instance_count
= parameters
->u
.direct
.instance_count
;
1776 if (!instance_count
)
1779 if (parameters
->indexed
)
1780 VK_CALL(vkCmdDrawIndexed(vk_command_buffer
, parameters
->u
.direct
.index_count
,
1781 instance_count
, parameters
->u
.direct
.start_idx
, parameters
->u
.direct
.base_vertex_idx
,
1782 parameters
->u
.direct
.start_instance
));
1784 VK_CALL(vkCmdDraw(vk_command_buffer
, parameters
->u
.direct
.index_count
, instance_count
,
1785 parameters
->u
.direct
.start_idx
, parameters
->u
.direct
.start_instance
));
1788 if (context_vk
->c
.transform_feedback_active
)
1790 VK_CALL(vkCmdEndTransformFeedbackEXT(vk_command_buffer
, 0, ARRAY_SIZE(context_vk
->vk_so_counters
),
1791 context_vk
->vk_so_counters
, context_vk
->vk_so_offsets
));
1792 context_vk
->c
.transform_feedback_paused
= 1;
1793 context_vk
->c
.transform_feedback_active
= 0;
1796 context_release(&context_vk
->c
);
1799 static void adapter_vk_dispatch_compute(struct wined3d_device
*device
,
1800 const struct wined3d_state
*state
, const struct wined3d_dispatch_parameters
*parameters
)
1802 struct wined3d_buffer_vk
*indirect_vk
= NULL
;
1803 const struct wined3d_vk_info
*vk_info
;
1804 struct wined3d_context_vk
*context_vk
;
1805 VkCommandBuffer vk_command_buffer
;
1807 TRACE("device %p, state %p, parameters %p.\n", device
, state
, parameters
);
1809 context_vk
= wined3d_context_vk(context_acquire(device
, NULL
, 0));
1810 vk_info
= context_vk
->vk_info
;
1812 if (parameters
->indirect
)
1813 indirect_vk
= wined3d_buffer_vk(parameters
->u
.indirect
.buffer
);
1815 if (!(vk_command_buffer
= wined3d_context_vk_apply_compute_state(context_vk
, state
, indirect_vk
)))
1817 ERR("Failed to apply compute state.\n");
1818 context_release(&context_vk
->c
);
1822 if (parameters
->indirect
)
1824 struct wined3d_bo_vk
*bo
= wined3d_bo_vk(indirect_vk
->b
.buffer_object
);
1826 wined3d_context_vk_reference_bo(context_vk
, bo
);
1827 VK_CALL(vkCmdDispatchIndirect(vk_command_buffer
, bo
->vk_buffer
,
1828 bo
->b
.buffer_offset
+ parameters
->u
.indirect
.offset
));
1832 const struct wined3d_direct_dispatch_parameters
*direct
= ¶meters
->u
.direct
;
1834 VK_CALL(vkCmdDispatch(vk_command_buffer
, direct
->group_count_x
, direct
->group_count_y
, direct
->group_count_z
));
1837 VK_CALL(vkCmdPipelineBarrier(vk_command_buffer
, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
,
1838 VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT
, 0, 0, NULL
, 0, NULL
, 0, NULL
));
1840 context_release(&context_vk
->c
);
1843 static void adapter_vk_clear_uav(struct wined3d_context
*context
,
1844 struct wined3d_unordered_access_view
*view
, const struct wined3d_uvec4
*clear_value
, bool fp
)
1846 TRACE("context %p, view %p, clear_value %s.\n", context
, view
, debug_uvec4(clear_value
));
1848 wined3d_unordered_access_view_vk_clear(wined3d_unordered_access_view_vk(view
),
1849 clear_value
, wined3d_context_vk(context
), fp
);
1852 static void adapter_vk_generate_mipmap(struct wined3d_context
*context
, struct wined3d_shader_resource_view
*view
)
1854 TRACE("context %p, view %p.\n", context
, view
);
1856 wined3d_shader_resource_view_vk_generate_mipmap(wined3d_shader_resource_view_vk(view
),
1857 wined3d_context_vk(context
));
1860 static const struct wined3d_adapter_ops wined3d_adapter_vk_ops
=
1862 .adapter_destroy
= adapter_vk_destroy
,
1863 .adapter_create_device
= adapter_vk_create_device
,
1864 .adapter_destroy_device
= adapter_vk_destroy_device
,
1865 .adapter_acquire_context
= adapter_vk_acquire_context
,
1866 .adapter_release_context
= adapter_vk_release_context
,
1867 .adapter_get_wined3d_caps
= adapter_vk_get_wined3d_caps
,
1868 .adapter_check_format
= adapter_vk_check_format
,
1869 .adapter_init_3d
= adapter_vk_init_3d
,
1870 .adapter_uninit_3d
= adapter_vk_uninit_3d
,
1871 .adapter_map_bo_address
= adapter_vk_map_bo_address
,
1872 .adapter_unmap_bo_address
= adapter_vk_unmap_bo_address
,
1873 .adapter_copy_bo_address
= adapter_vk_copy_bo_address
,
1874 .adapter_flush_bo_address
= adapter_vk_flush_bo_address
,
1875 .adapter_alloc_bo
= adapter_vk_alloc_bo
,
1876 .adapter_destroy_bo
= adapter_vk_destroy_bo
,
1877 .adapter_create_swapchain
= adapter_vk_create_swapchain
,
1878 .adapter_destroy_swapchain
= adapter_vk_destroy_swapchain
,
1879 .adapter_create_buffer
= adapter_vk_create_buffer
,
1880 .adapter_destroy_buffer
= adapter_vk_destroy_buffer
,
1881 .adapter_create_texture
= adapter_vk_create_texture
,
1882 .adapter_destroy_texture
= adapter_vk_destroy_texture
,
1883 .adapter_create_rendertarget_view
= adapter_vk_create_rendertarget_view
,
1884 .adapter_destroy_rendertarget_view
= adapter_vk_destroy_rendertarget_view
,
1885 .adapter_create_shader_resource_view
= adapter_vk_create_shader_resource_view
,
1886 .adapter_destroy_shader_resource_view
= adapter_vk_destroy_shader_resource_view
,
1887 .adapter_create_unordered_access_view
= adapter_vk_create_unordered_access_view
,
1888 .adapter_destroy_unordered_access_view
= adapter_vk_destroy_unordered_access_view
,
1889 .adapter_create_sampler
= adapter_vk_create_sampler
,
1890 .adapter_destroy_sampler
= adapter_vk_destroy_sampler
,
1891 .adapter_create_query
= adapter_vk_create_query
,
1892 .adapter_destroy_query
= adapter_vk_destroy_query
,
1893 .adapter_flush_context
= adapter_vk_flush_context
,
1894 .adapter_draw_primitive
= adapter_vk_draw_primitive
,
1895 .adapter_dispatch_compute
= adapter_vk_dispatch_compute
,
1896 .adapter_clear_uav
= adapter_vk_clear_uav
,
1897 .adapter_generate_mipmap
= adapter_vk_generate_mipmap
,
1900 static unsigned int wined3d_get_wine_vk_version(void)
1902 const char * (CDECL
*wine_get_version
)(void) = (void *)GetProcAddress( GetModuleHandleW(L
"ntdll.dll"),
1903 "wine_get_version" );
1907 if (!wine_get_version
) return VK_MAKE_VERSION(1, 0, 0);
1909 ptr
= wine_get_version();
1912 while (isdigit(*ptr
))
1919 return VK_MAKE_VERSION(major
, minor
, 0);
1925 unsigned int core_since_version
;
1928 vulkan_instance_extensions
[] =
1930 {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
, VK_API_VERSION_1_1
, FALSE
},
1931 {VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME
, VK_API_VERSION_1_1
, FALSE
},
1932 {VK_KHR_SURFACE_EXTENSION_NAME
, ~0u, TRUE
},
1933 {VK_KHR_WIN32_SURFACE_EXTENSION_NAME
, ~0u, TRUE
},
1936 static BOOL
enable_vulkan_instance_extensions(uint32_t *extension_count
,
1937 const char *enabled_extensions
[], const struct wined3d_vk_info
*vk_info
)
1939 PFN_vkEnumerateInstanceExtensionProperties pfn_vkEnumerateInstanceExtensionProperties
;
1940 VkExtensionProperties
*extensions
= NULL
;
1941 BOOL success
= FALSE
, found
;
1942 unsigned int i
, j
, count
;
1945 *extension_count
= 0;
1947 if (!(pfn_vkEnumerateInstanceExtensionProperties
1948 = (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceExtensionProperties"))))
1950 WARN("Failed to get 'vkEnumerateInstanceExtensionProperties'.\n");
1954 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, NULL
)) < 0)
1956 WARN("Failed to count instance extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
1959 if (!(extensions
= heap_calloc(count
, sizeof(*extensions
))))
1961 WARN("Out of memory.\n");
1964 if ((vr
= pfn_vkEnumerateInstanceExtensionProperties(NULL
, &count
, extensions
)) < 0)
1966 WARN("Failed to enumerate extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
1970 TRACE("Vulkan instance extensions reported:\n");
1971 for (i
= 0; i
< count
; ++i
)
1973 TRACE(" - %s.\n", debugstr_a(extensions
[i
].extensionName
));
1976 for (i
= 0; i
< ARRAY_SIZE(vulkan_instance_extensions
); ++i
)
1978 if (vulkan_instance_extensions
[i
].core_since_version
<= vk_info
->api_version
)
1981 for (j
= 0, found
= FALSE
; j
< count
; ++j
)
1983 if (!strcmp(extensions
[j
].extensionName
, vulkan_instance_extensions
[i
].name
))
1991 TRACE("Enabling instance extension '%s'.\n", vulkan_instance_extensions
[i
].name
);
1992 enabled_extensions
[(*extension_count
)++] = vulkan_instance_extensions
[i
].name
;
1994 else if (!found
&& vulkan_instance_extensions
[i
].required
)
1996 WARN("Required extension '%s' is not available.\n", vulkan_instance_extensions
[i
].name
);
2003 heap_free(extensions
);
2007 static BOOL
wined3d_init_vulkan(struct wined3d_vk_info
*vk_info
)
2009 const char *enabled_instance_extensions
[ARRAY_SIZE(vulkan_instance_extensions
)];
2010 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion
;
2011 struct vulkan_ops
*vk_ops
= &vk_info
->vk_ops
;
2012 VkInstance instance
= VK_NULL_HANDLE
;
2013 VkInstanceCreateInfo instance_info
;
2014 VkApplicationInfo app_info
;
2015 uint32_t api_version
= 0;
2016 char app_name
[MAX_PATH
];
2019 if (!wined3d_load_vulkan(vk_info
))
2022 if (!(vk_ops
->vkCreateInstance
= (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkCreateInstance"))))
2024 ERR("Failed to get 'vkCreateInstance'.\n");
2028 vk_info
->api_version
= VK_API_VERSION_1_0
;
2029 if ((pfn_vkEnumerateInstanceVersion
= (void *)VK_CALL(vkGetInstanceProcAddr(NULL
, "vkEnumerateInstanceVersion")))
2030 && pfn_vkEnumerateInstanceVersion(&api_version
) == VK_SUCCESS
)
2032 TRACE("Vulkan instance API version %s.\n", debug_vk_version(api_version
));
2034 if (api_version
>= VK_API_VERSION_1_1
)
2035 vk_info
->api_version
= VK_API_VERSION_1_1
;
2038 memset(&app_info
, 0, sizeof(app_info
));
2039 app_info
.sType
= VK_STRUCTURE_TYPE_APPLICATION_INFO
;
2040 if (wined3d_get_app_name(app_name
, ARRAY_SIZE(app_name
)))
2041 app_info
.pApplicationName
= app_name
;
2042 app_info
.pEngineName
= "Damavand";
2043 app_info
.engineVersion
= wined3d_get_wine_vk_version();
2044 app_info
.apiVersion
= vk_info
->api_version
;
2046 memset(&instance_info
, 0, sizeof(instance_info
));
2047 instance_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
2048 instance_info
.pApplicationInfo
= &app_info
;
2049 instance_info
.ppEnabledExtensionNames
= enabled_instance_extensions
;
2050 if (!enable_vulkan_instance_extensions(&instance_info
.enabledExtensionCount
, enabled_instance_extensions
, vk_info
))
2053 memset(vk_info
->supported
, 0, sizeof(vk_info
->supported
));
2054 vk_info
->supported
[WINED3D_VK_EXT_NONE
] = TRUE
;
2056 if ((vr
= VK_CALL(vkCreateInstance(&instance_info
, NULL
, &instance
))) < 0)
2058 WARN("Failed to create Vulkan instance, vr %s.\n", wined3d_debug_vkresult(vr
));
2062 TRACE("Created Vulkan instance %p.\n", instance
);
2064 #define LOAD_INSTANCE_PFN(name) \
2065 if (!(vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name)))) \
2067 WARN("Could not get instance proc addr for '" #name "'.\n"); \
2070 #define LOAD_INSTANCE_OPT_PFN(name) \
2071 vk_ops->name = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #name));
2072 #define VK_INSTANCE_PFN LOAD_INSTANCE_PFN
2073 #define VK_INSTANCE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2074 #define VK_DEVICE_PFN LOAD_INSTANCE_PFN
2075 #define VK_DEVICE_EXT_PFN LOAD_INSTANCE_OPT_PFN
2078 #undef VK_INSTANCE_PFN
2079 #undef VK_INSTANCE_EXT_PFN
2080 #undef VK_DEVICE_PFN
2081 #undef VK_DEVICE_EXT_PFN
2083 #define MAP_INSTANCE_FUNCTION(core_pfn, ext_pfn) \
2084 if (!vk_ops->core_pfn) \
2085 vk_ops->core_pfn = (void *)VK_CALL(vkGetInstanceProcAddr(instance, #ext_pfn));
2086 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceProperties2
, vkGetPhysicalDeviceProperties2KHR
)
2087 MAP_INSTANCE_FUNCTION(vkGetPhysicalDeviceFeatures2
, vkGetPhysicalDeviceFeatures2KHR
)
2088 #undef MAP_INSTANCE_FUNCTION
2090 vk_info
->instance
= instance
;
2095 if (vk_ops
->vkDestroyInstance
)
2096 VK_CALL(vkDestroyInstance(instance
, NULL
));
2097 wined3d_unload_vulkan(vk_info
);
2101 static VkPhysicalDevice
get_vulkan_physical_device(struct wined3d_vk_info
*vk_info
)
2103 VkPhysicalDevice physical_devices
[1];
2107 if ((vr
= VK_CALL(vkEnumeratePhysicalDevices(vk_info
->instance
, &count
, NULL
))) < 0)
2109 WARN("Failed to enumerate physical devices, vr %s.\n", wined3d_debug_vkresult(vr
));
2110 return VK_NULL_HANDLE
;
2114 WARN("No physical device.\n");
2115 return VK_NULL_HANDLE
;
2119 /* TODO: Create wined3d_adapter for each device. */
2120 FIXME("Multiple physical devices available.\n");
2124 if ((vr
= VK_CALL(vkEnumeratePhysicalDevices(vk_info
->instance
, &count
, physical_devices
))) < 0)
2126 WARN("Failed to get physical devices, vr %s.\n", wined3d_debug_vkresult(vr
));
2127 return VK_NULL_HANDLE
;
2130 return physical_devices
[0];
2133 static enum wined3d_display_driver
guess_display_driver(enum wined3d_pci_vendor vendor
)
2137 case HW_VENDOR_AMD
: return DRIVER_AMD_RX
;
2138 case HW_VENDOR_INTEL
: return DRIVER_INTEL_HD4000
;
2139 case HW_VENDOR_NVIDIA
: return DRIVER_NVIDIA_GEFORCE8
;
2140 default: return DRIVER_WINE
;
2144 static bool adapter_vk_init_driver_info(struct wined3d_adapter_vk
*adapter_vk
,
2145 const VkPhysicalDeviceProperties
*properties
)
2147 const VkPhysicalDeviceMemoryProperties
*memory_properties
= &adapter_vk
->memory_properties
;
2148 const struct wined3d_gpu_description
*gpu_description
;
2149 struct wined3d_gpu_description description
;
2150 UINT64 vram_bytes
, sysmem_bytes
;
2151 const VkMemoryType
*type
;
2152 const VkMemoryHeap
*heap
;
2155 TRACE("Device name: %s.\n", debugstr_a(properties
->deviceName
));
2156 TRACE("Vendor ID: 0x%04x, Device ID: 0x%04x.\n", properties
->vendorID
, properties
->deviceID
);
2157 TRACE("Driver version: %#x.\n", properties
->driverVersion
);
2158 TRACE("API version: %s.\n", debug_vk_version(properties
->apiVersion
));
2160 for (i
= 0, vram_bytes
= 0, sysmem_bytes
= 0; i
< memory_properties
->memoryHeapCount
; ++i
)
2162 heap
= &memory_properties
->memoryHeaps
[i
];
2163 TRACE("Memory heap [%u]: flags %#x, size 0x%s.\n",
2164 i
, heap
->flags
, wine_dbgstr_longlong(heap
->size
));
2165 if (heap
->flags
& VK_MEMORY_HEAP_DEVICE_LOCAL_BIT
)
2166 vram_bytes
+= heap
->size
;
2168 sysmem_bytes
+= heap
->size
;
2170 TRACE("Total device memory: 0x%s.\n", wine_dbgstr_longlong(vram_bytes
));
2171 TRACE("Total shared system memory: 0x%s.\n", wine_dbgstr_longlong(sysmem_bytes
));
2173 for (i
= 0; i
< memory_properties
->memoryTypeCount
; ++i
)
2175 type
= &memory_properties
->memoryTypes
[i
];
2176 TRACE("Memory type [%u]: flags %#x, heap %u.\n", i
, type
->propertyFlags
, type
->heapIndex
);
2179 if (!(gpu_description
= wined3d_get_user_override_gpu_description(properties
->vendorID
, properties
->deviceID
)))
2180 gpu_description
= wined3d_get_gpu_description(properties
->vendorID
, properties
->deviceID
);
2182 if (!gpu_description
)
2184 FIXME("Failed to retrieve GPU description for device %s %04x:%04x.\n",
2185 debugstr_a(properties
->deviceName
), properties
->vendorID
, properties
->deviceID
);
2187 description
.vendor
= properties
->vendorID
;
2188 description
.device
= properties
->deviceID
;
2189 description
.description
= properties
->deviceName
;
2190 description
.driver
= guess_display_driver(properties
->vendorID
);
2191 description
.vidmem
= vram_bytes
;
2193 gpu_description
= &description
;
2196 return wined3d_driver_info_init(&adapter_vk
->a
.driver_info
, gpu_description
,
2197 adapter_vk
->a
.d3d_info
.feature_level
, vram_bytes
, sysmem_bytes
);
2200 static bool feature_level_9_2_supported(const struct wined3d_physical_device_info
*info
)
2202 return info
->features2
.features
.occlusionQueryPrecise
;
2205 static bool feature_level_9_3_supported(const struct wined3d_physical_device_info
*info
, unsigned int shader_model
)
2207 return shader_model
>= 3
2208 && info
->features2
.features
.independentBlend
;
2211 static bool feature_level_10_supported(const struct wined3d_physical_device_info
*info
, unsigned int shader_model
)
2213 return shader_model
>= 4
2214 && info
->features2
.features
.multiViewport
2215 && info
->features2
.features
.geometryShader
2216 && info
->features2
.features
.depthClamp
2217 && info
->features2
.features
.depthBiasClamp
2218 && info
->features2
.features
.pipelineStatisticsQuery
2219 && info
->features2
.features
.shaderClipDistance
2220 && info
->features2
.features
.shaderCullDistance
2221 && info
->vertex_divisor_features
.vertexAttributeInstanceRateDivisor
2222 && info
->vertex_divisor_features
.vertexAttributeInstanceRateZeroDivisor
;
2225 static bool feature_level_10_1_supported(const struct wined3d_physical_device_info
*info
, unsigned int shader_model
)
2227 return info
->features2
.features
.imageCubeArray
;
2230 static bool feature_level_11_supported(const struct wined3d_physical_device_info
*info
, unsigned int shader_model
)
2232 return shader_model
>= 5
2233 && info
->features2
.features
.multiDrawIndirect
2234 && info
->features2
.features
.drawIndirectFirstInstance
2235 && info
->features2
.features
.fragmentStoresAndAtomics
2236 && info
->features2
.features
.shaderImageGatherExtended
2237 && info
->features2
.features
.tessellationShader
;
2240 static bool feature_level_11_1_supported(const struct wined3d_physical_device_info
*info
)
2242 return info
->features2
.features
.vertexPipelineStoresAndAtomics
;
2245 static enum wined3d_feature_level
feature_level_from_caps(const struct wined3d_physical_device_info
*info
,
2246 const struct shader_caps
*shader_caps
)
2248 unsigned int shader_model
;
2250 shader_model
= min(shader_caps
->vs_version
, shader_caps
->ps_version
);
2251 shader_model
= min(shader_model
, max(shader_caps
->gs_version
, 3));
2252 shader_model
= min(shader_model
, max(shader_caps
->hs_version
, 4));
2253 shader_model
= min(shader_model
, max(shader_caps
->ds_version
, 4));
2256 return WINED3D_FEATURE_LEVEL_7
;
2258 if (shader_model
<= 1)
2259 return WINED3D_FEATURE_LEVEL_8
;
2261 if (!feature_level_9_2_supported(info
))
2262 return WINED3D_FEATURE_LEVEL_9_1
;
2264 if (!feature_level_9_3_supported(info
, shader_model
))
2265 return WINED3D_FEATURE_LEVEL_9_2
;
2267 if (!feature_level_10_supported(info
, shader_model
))
2268 return WINED3D_FEATURE_LEVEL_9_3
;
2270 if (!feature_level_10_1_supported(info
, shader_model
))
2271 return WINED3D_FEATURE_LEVEL_10
;
2273 if (!feature_level_11_supported(info
, shader_model
))
2274 return WINED3D_FEATURE_LEVEL_10_1
;
2276 if (!feature_level_11_1_supported(info
))
2277 return WINED3D_FEATURE_LEVEL_11
;
2279 return WINED3D_FEATURE_LEVEL_11_1
;
2282 static void wined3d_adapter_vk_init_d3d_info(struct wined3d_adapter_vk
*adapter_vk
, uint32_t wined3d_creation_flags
)
2284 struct wined3d_d3d_info
*d3d_info
= &adapter_vk
->a
.d3d_info
;
2285 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
2286 struct wined3d_physical_device_info device_info
;
2287 struct wined3d_vertex_caps vertex_caps
;
2288 struct fragment_caps fragment_caps
;
2289 unsigned int sample_counts_mask
;
2290 struct shader_caps shader_caps
;
2292 get_physical_device_info(adapter_vk
, &device_info
);
2294 adapter_vk
->a
.shader_backend
->shader_get_caps(&adapter_vk
->a
, &shader_caps
);
2295 adapter_vk
->a
.vertex_pipe
->vp_get_caps(&adapter_vk
->a
, &vertex_caps
);
2296 adapter_vk
->a
.fragment_pipe
->get_caps(&adapter_vk
->a
, &fragment_caps
);
2298 d3d_info
->limits
.vs_version
= shader_caps
.vs_version
;
2299 d3d_info
->limits
.hs_version
= shader_caps
.hs_version
;
2300 d3d_info
->limits
.ds_version
= shader_caps
.ds_version
;
2301 d3d_info
->limits
.gs_version
= shader_caps
.gs_version
;
2302 d3d_info
->limits
.ps_version
= shader_caps
.ps_version
;
2303 d3d_info
->limits
.cs_version
= shader_caps
.cs_version
;
2304 d3d_info
->limits
.vs_uniform_count
= shader_caps
.vs_uniform_count
;
2305 d3d_info
->limits
.ps_uniform_count
= shader_caps
.ps_uniform_count
;
2306 d3d_info
->limits
.varying_count
= shader_caps
.varying_count
;
2307 d3d_info
->limits
.ffp_textures
= fragment_caps
.MaxSimultaneousTextures
;
2308 d3d_info
->limits
.ffp_blend_stages
= fragment_caps
.MaxTextureBlendStages
;
2309 d3d_info
->limits
.ffp_vertex_blend_matrices
= vertex_caps
.max_vertex_blend_matrices
;
2310 d3d_info
->limits
.active_light_count
= vertex_caps
.max_active_lights
;
2312 d3d_info
->limits
.max_rt_count
= WINED3D_MAX_RENDER_TARGETS
;
2313 d3d_info
->limits
.max_clip_distances
= WINED3D_MAX_CLIP_DISTANCES
;
2314 d3d_info
->limits
.texture_size
= adapter_vk
->device_limits
.maxImageDimension2D
;
2315 d3d_info
->limits
.pointsize_max
= adapter_vk
->device_limits
.pointSizeRange
[1];
2316 sample_counts_mask
= adapter_vk
->device_limits
.framebufferColorSampleCounts
2317 | adapter_vk
->device_limits
.framebufferDepthSampleCounts
2318 | adapter_vk
->device_limits
.framebufferStencilSampleCounts
2319 | adapter_vk
->device_limits
.framebufferNoAttachmentsSampleCounts
;
2320 d3d_info
->limits
.sample_count
= (1u << wined3d_log2i(sample_counts_mask
));
2322 d3d_info
->wined3d_creation_flags
= wined3d_creation_flags
;
2324 d3d_info
->xyzrhw
= vertex_caps
.xyzrhw
;
2325 d3d_info
->emulated_flatshading
= vertex_caps
.emulated_flatshading
;
2326 d3d_info
->ffp_generic_attributes
= vertex_caps
.ffp_generic_attributes
;
2327 d3d_info
->ffp_alpha_test
= false;
2328 d3d_info
->vs_clipping
= !!(shader_caps
.wined3d_caps
& WINED3D_SHADER_CAP_VS_CLIPPING
);
2329 d3d_info
->shader_color_key
= !!(fragment_caps
.wined3d_caps
& WINED3D_FRAGMENT_CAP_COLOR_KEY
);
2330 d3d_info
->shader_double_precision
= !!(shader_caps
.wined3d_caps
& WINED3D_SHADER_CAP_DOUBLE_PRECISION
);
2331 d3d_info
->shader_output_interpolation
= !!(shader_caps
.wined3d_caps
& WINED3D_SHADER_CAP_OUTPUT_INTERPOLATION
);
2332 d3d_info
->viewport_array_index_any_shader
= false; /* VK_EXT_shader_viewport_index_layer */
2333 d3d_info
->texture_npot
= true;
2334 d3d_info
->texture_npot_conditional
= true;
2335 d3d_info
->normalized_texrect
= false;
2336 d3d_info
->draw_base_vertex_offset
= true;
2337 d3d_info
->vertex_bgra
= true;
2338 d3d_info
->texture_swizzle
= true;
2339 d3d_info
->srgb_read_control
= false;
2340 d3d_info
->srgb_write_control
= false;
2341 d3d_info
->clip_control
= true;
2342 d3d_info
->full_ffp_varyings
= !!(shader_caps
.wined3d_caps
& WINED3D_SHADER_CAP_FULL_FFP_VARYINGS
);
2343 d3d_info
->scaled_resolve
= false;
2344 d3d_info
->pbo
= true;
2345 d3d_info
->feature_level
= feature_level_from_caps(&device_info
, &shader_caps
);
2346 d3d_info
->subpixel_viewport
= true;
2347 d3d_info
->fences
= true;
2348 d3d_info
->persistent_map
= true;
2350 /* Like GL, Vulkan doesn't explicitly specify a filling convention and only mandates that a
2351 * shared edge of two adjacent triangles generate a fragment for exactly one of the triangles.
2353 * However, every Vulkan implementation we have seen so far uses a top-left rule. Hardware
2354 * that differs either predates Vulkan (d3d9 class HW, GeForce 9xxx) or behaves the way we
2355 * want in Vulkan (MacOS Radeon driver through MoltenVK). */
2356 d3d_info
->filling_convention_offset
= 0.0f
;
2358 d3d_info
->multisample_draw_location
= WINED3D_LOCATION_TEXTURE_RGB
;
2360 vk_info
->multiple_viewports
= device_info
.features2
.features
.multiViewport
;
2363 static bool wined3d_adapter_vk_init_device_extensions(struct wined3d_adapter_vk
*adapter_vk
)
2365 VkPhysicalDevice physical_device
= adapter_vk
->physical_device
;
2366 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
2367 unsigned int count
, enable_count
, i
, j
;
2368 const char **enabled_extensions
= NULL
;
2369 VkExtensionProperties
*extensions
;
2370 bool found
, success
= false;
2371 SIZE_T enable_size
= 0;
2377 unsigned int core_since_version
;
2382 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME
, ~0u},
2383 {VK_EXT_VERTEX_ATTRIBUTE_DIVISOR_EXTENSION_NAME
, ~0u, true},
2384 {VK_KHR_MAINTENANCE1_EXTENSION_NAME
, VK_API_VERSION_1_1
, true},
2385 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME
,VK_API_VERSION_1_2
},
2386 {VK_KHR_SHADER_DRAW_PARAMETERS_EXTENSION_NAME
, VK_API_VERSION_1_1
, true},
2387 {VK_KHR_SWAPCHAIN_EXTENSION_NAME
, ~0u, true},
2388 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME
, VK_API_VERSION_1_2
},
2394 enum wined3d_vk_extension extension
;
2398 {VK_EXT_TRANSFORM_FEEDBACK_EXTENSION_NAME
, WINED3D_VK_EXT_TRANSFORM_FEEDBACK
},
2399 {VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE_EXTENSION_NAME
, WINED3D_VK_KHR_SAMPLER_MIRROR_CLAMP_TO_EDGE
},
2400 {VK_EXT_HOST_QUERY_RESET_EXTENSION_NAME
, WINED3D_VK_EXT_HOST_QUERY_RESET
},
2403 if ((vr
= VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device
, NULL
, &count
, NULL
))) < 0)
2405 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
2409 if (!(extensions
= heap_calloc(count
, sizeof(*extensions
))))
2411 ERR("Failed to allocate extension properties array.\n");
2415 if ((vr
= VK_CALL(vkEnumerateDeviceExtensionProperties(physical_device
, NULL
, &count
, extensions
))) < 0)
2417 ERR("Failed to enumerate device extensions, vr %s.\n", wined3d_debug_vkresult(vr
));
2421 TRACE("Vulkan device extensions reported:\n");
2422 for (i
= 0; i
< count
; ++i
)
2424 TRACE(" - %s.\n", debugstr_a(extensions
[i
].extensionName
));
2427 for (i
= 0, enable_count
= 0; i
< ARRAY_SIZE(info
); ++i
)
2429 if (info
[i
].core_since_version
<= vk_info
->api_version
)
2432 for (j
= 0, found
= false; j
< count
; ++j
)
2434 if (!strcmp(extensions
[j
].extensionName
, info
[i
].name
))
2443 if (!info
[i
].required
)
2445 WARN("Required extension '%s' is not available.\n", info
[i
].name
);
2449 TRACE("Enabling device extension '%s'.\n", info
[i
].name
);
2450 if (!wined3d_array_reserve((void **)&enabled_extensions
, &enable_size
,
2451 enable_count
+ 1, sizeof(*enabled_extensions
)))
2453 ERR("Failed to allocate enabled extensions array.\n");
2456 enabled_extensions
[enable_count
++] = info
[i
].name
;
2460 for (i
= 0; i
< ARRAY_SIZE(map
); ++i
)
2462 for (j
= 0; j
< enable_count
; ++j
)
2464 if (!strcmp(enabled_extensions
[j
], map
[i
].name
))
2466 vk_info
->supported
[map
[i
].extension
] = TRUE
;
2475 adapter_vk
->device_extension_count
= enable_count
;
2476 adapter_vk
->device_extensions
= enabled_extensions
;
2480 heap_free(enabled_extensions
);
2482 heap_free(extensions
);
2486 static BOOL
wined3d_adapter_vk_init(struct wined3d_adapter_vk
*adapter_vk
,
2487 unsigned int ordinal
, unsigned int wined3d_creation_flags
)
2489 struct wined3d_vk_info
*vk_info
= &adapter_vk
->vk_info
;
2490 struct wined3d_adapter
*adapter
= &adapter_vk
->a
;
2491 VkPhysicalDeviceIDProperties id_properties
;
2492 VkPhysicalDeviceProperties2 properties2
;
2493 LUID primary_luid
, *luid
= NULL
;
2495 TRACE("adapter_vk %p, ordinal %u, wined3d_creation_flags %#x.\n",
2496 adapter_vk
, ordinal
, wined3d_creation_flags
);
2498 if (!wined3d_init_vulkan(vk_info
))
2500 WARN("Failed to initialize Vulkan.\n");
2504 if (!(adapter_vk
->physical_device
= get_vulkan_physical_device(vk_info
)))
2507 if (!wined3d_adapter_vk_init_device_extensions(adapter_vk
))
2510 memset(&id_properties
, 0, sizeof(id_properties
));
2511 id_properties
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
2512 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
2513 properties2
.pNext
= &id_properties
;
2515 if (vk_info
->vk_ops
.vkGetPhysicalDeviceProperties2
)
2516 VK_CALL(vkGetPhysicalDeviceProperties2(adapter_vk
->physical_device
, &properties2
));
2518 VK_CALL(vkGetPhysicalDeviceProperties(adapter_vk
->physical_device
, &properties2
.properties
));
2519 adapter_vk
->device_limits
= properties2
.properties
.limits
;
2521 VK_CALL(vkGetPhysicalDeviceMemoryProperties(adapter_vk
->physical_device
, &adapter_vk
->memory_properties
));
2523 if (id_properties
.deviceLUIDValid
)
2524 luid
= (LUID
*)id_properties
.deviceLUID
;
2525 else if (ordinal
== 0 && wined3d_get_primary_adapter_luid(&primary_luid
))
2526 luid
= &primary_luid
;
2528 if (!wined3d_adapter_init(adapter
, ordinal
, luid
, &wined3d_adapter_vk_ops
))
2530 heap_free(adapter_vk
->device_extensions
);
2534 adapter
->vertex_pipe
= wined3d_spirv_vertex_pipe_init_vk();
2535 adapter
->fragment_pipe
= wined3d_spirv_fragment_pipe_init_vk();
2536 adapter
->misc_state_template
= misc_state_template_vk
;
2537 adapter
->shader_backend
= wined3d_spirv_shader_backend_init_vk();
2539 wined3d_adapter_vk_init_d3d_info(adapter_vk
, wined3d_creation_flags
);
2541 if (!adapter_vk_init_driver_info(adapter_vk
, &properties2
.properties
))
2543 TRACE("Reporting (fake) driver version 0x%08x-0x%08x.\n",
2544 adapter_vk
->a
.driver_info
.version_high
, adapter_vk
->a
.driver_info
.version_low
);
2545 adapter
->vram_bytes_used
= 0;
2546 TRACE("Emulating 0x%s bytes of video ram.\n", wine_dbgstr_longlong(adapter
->driver_info
.vram_bytes
));
2548 memcpy(&adapter
->driver_uuid
, id_properties
.driverUUID
, sizeof(adapter
->driver_uuid
));
2549 memcpy(&adapter
->device_uuid
, id_properties
.deviceUUID
, sizeof(adapter
->device_uuid
));
2551 if (!wined3d_adapter_vk_init_format_info(adapter_vk
, vk_info
))
2557 wined3d_adapter_cleanup(adapter
);
2558 heap_free(adapter_vk
->device_extensions
);
2560 VK_CALL(vkDestroyInstance(vk_info
->instance
, NULL
));
2561 wined3d_unload_vulkan(vk_info
);
2565 struct wined3d_adapter
*wined3d_adapter_vk_create(unsigned int ordinal
,
2566 unsigned int wined3d_creation_flags
)
2568 struct wined3d_adapter_vk
*adapter_vk
;
2570 if (!(adapter_vk
= heap_alloc_zero(sizeof(*adapter_vk
))))
2573 if (!wined3d_adapter_vk_init(adapter_vk
, ordinal
, wined3d_creation_flags
))
2575 heap_free(adapter_vk
);
2579 TRACE("Created adapter %p.\n", adapter_vk
);
2581 return &adapter_vk
->a
;