2 * Copyright 2018 Józef Kucia 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
20 #include "wine/heap.h"
21 #include "wine/vulkan.h"
22 #include "wine/test.h"
24 static VkResult
create_instance(uint32_t extension_count
,
25 const char * const *enabled_extensions
, VkInstance
*vk_instance
)
27 VkInstanceCreateInfo create_info
;
29 create_info
.sType
= VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO
;
30 create_info
.pNext
= NULL
;
31 create_info
.flags
= 0;
32 create_info
.pApplicationInfo
= NULL
;
33 create_info
.enabledLayerCount
= 0;
34 create_info
.ppEnabledLayerNames
= NULL
;
35 create_info
.enabledExtensionCount
= extension_count
;
36 create_info
.ppEnabledExtensionNames
= enabled_extensions
;
38 return vkCreateInstance(&create_info
, NULL
, vk_instance
);
41 #define create_instance_skip(a, b, c) create_instance_skip_(__LINE__, a, b, c)
42 static VkResult
create_instance_skip_(unsigned int line
, uint32_t extension_count
,
43 const char * const *enabled_extensions
, VkInstance
*vk_instance
)
47 if ((vr
= create_instance(extension_count
, enabled_extensions
, vk_instance
)) >= 0)
52 case VK_ERROR_EXTENSION_NOT_PRESENT
:
53 if (extension_count
== 1)
54 skip_(__FILE__
, line
)("Instance extension '%s' not supported.\n", enabled_extensions
[0]);
56 skip_(__FILE__
, line
)("Instance extensions not supported.\n");
60 skip_(__FILE__
, line
)("Failed to create Vulkan instance, vr %d.\n", vr
);
67 static VkBool32
find_queue_family(VkPhysicalDevice vk_physical_device
,
68 VkQueueFlags flags
, uint32_t *family_index
)
70 VkQueueFamilyProperties
*properties
;
71 VkBool32 ret
= VK_FALSE
;
74 vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device
, &count
, NULL
);
75 properties
= heap_calloc(count
, sizeof(*properties
));
76 ok(!!properties
, "Failed to allocate memory.\n");
77 vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device
, &count
, properties
);
79 for (i
= 0; i
< count
; ++i
)
81 if ((properties
[i
].queueFlags
& flags
) == flags
)
89 heap_free(properties
);
93 static VkResult
create_device(VkPhysicalDevice vk_physical_device
,
94 uint32_t extension_count
, const char * const *enabled_extensions
,
95 const void *next
, VkDevice
*vk_device
)
97 VkDeviceQueueCreateInfo queue_info
;
98 VkDeviceCreateInfo create_info
;
99 float priority
= 0.0f
;
101 queue_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO
;
102 queue_info
.pNext
= NULL
;
103 queue_info
.flags
= 0;
104 if (!find_queue_family(vk_physical_device
, VK_QUEUE_GRAPHICS_BIT
, &queue_info
.queueFamilyIndex
))
106 trace("Failed to find queue family.\n");
107 return VK_ERROR_INITIALIZATION_FAILED
;
109 queue_info
.queueCount
= 1;
110 queue_info
.pQueuePriorities
= &priority
;
112 create_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO
;
113 create_info
.pNext
= next
;
114 create_info
.flags
= 0;
115 create_info
.queueCreateInfoCount
= 1;
116 create_info
.pQueueCreateInfos
= &queue_info
;
117 create_info
.enabledLayerCount
= 0;
118 create_info
.ppEnabledLayerNames
= NULL
;
119 create_info
.enabledExtensionCount
= extension_count
;
120 create_info
.ppEnabledExtensionNames
= enabled_extensions
;
121 create_info
.pEnabledFeatures
= NULL
;
123 return vkCreateDevice(vk_physical_device
, &create_info
, NULL
, vk_device
);
126 static void test_instance_version(void)
128 PFN_vkEnumerateInstanceVersion pfn_vkEnumerateInstanceVersion
;
132 pfn_vkEnumerateInstanceVersion
= (PFN_vkEnumerateInstanceVersion
)vkGetInstanceProcAddr(
133 NULL
, "vkEnumerateInstanceVersion");
134 if (!pfn_vkEnumerateInstanceVersion
)
136 skip("vkEnumerateInstanceVersion() is not available.\n");
140 vr
= pfn_vkEnumerateInstanceVersion(&version
);
141 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
142 ok(version
>= VK_API_VERSION_1_0
, "Invalid version %#x.\n", version
);
143 trace("Vulkan version %u.%u.%u.\n",
144 VK_VERSION_MAJOR(version
), VK_VERSION_MINOR(version
), VK_VERSION_PATCH(version
));
147 static void enumerate_physical_device(VkPhysicalDevice vk_physical_device
)
149 VkPhysicalDeviceProperties properties
;
151 vkGetPhysicalDeviceProperties(vk_physical_device
, &properties
);
153 trace("Device '%s', %#x:%#x, driver version %u.%u.%u (%#x), api version %u.%u.%u.\n",
154 properties
.deviceName
, properties
.vendorID
, properties
.deviceID
,
155 VK_VERSION_MAJOR(properties
.driverVersion
), VK_VERSION_MINOR(properties
.driverVersion
),
156 VK_VERSION_PATCH(properties
.driverVersion
), properties
.driverVersion
,
157 VK_VERSION_MAJOR(properties
.apiVersion
), VK_VERSION_MINOR(properties
.apiVersion
),
158 VK_VERSION_PATCH(properties
.apiVersion
));
161 static void test_enumerate_physical_device2(void)
163 static const char *procs
[] = {"vkGetPhysicalDeviceProperties2", "vkGetPhysicalDeviceProperties2KHR"};
164 static const char *extensions
[] = {VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME
};
165 PFN_vkGetPhysicalDeviceProperties2 pfn_vkGetPhysicalDeviceProperties2
;
166 VkPhysicalDeviceProperties2 properties2
;
167 VkPhysicalDevice
*vk_physical_devices
;
168 VkPhysicalDeviceIDProperties id
;
169 VkInstance vk_instance
;
175 if ((vr
= create_instance_skip(ARRAY_SIZE(extensions
), extensions
, &vk_instance
)) < 0)
177 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
179 vr
= vkEnumeratePhysicalDevices(vk_instance
, &count
, NULL
);
182 skip("No physical devices. VkResult %d.\n", vr
);
183 vkDestroyInstance(vk_instance
, NULL
);
187 vk_physical_devices
= heap_calloc(count
, sizeof(*vk_physical_devices
));
188 ok(!!vk_physical_devices
, "Failed to allocate memory.\n");
189 vr
= vkEnumeratePhysicalDevices(vk_instance
, &count
, vk_physical_devices
);
190 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
192 for (i
= 0; i
< ARRAY_SIZE(procs
); ++i
)
194 pfn_vkGetPhysicalDeviceProperties2
195 = (PFN_vkGetPhysicalDeviceProperties2
)vkGetInstanceProcAddr(vk_instance
, procs
[i
]);
196 if (!pfn_vkGetPhysicalDeviceProperties2
)
198 skip("%s is not available.\n", procs
[i
]);
202 for (j
= 0; j
< count
; ++j
)
204 properties2
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
;
205 properties2
.pNext
= &id
;
207 memset(&id
, 0, sizeof(id
));
208 id
.sType
= VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_ID_PROPERTIES
;
210 pfn_vkGetPhysicalDeviceProperties2(vk_physical_devices
[j
], &properties2
);
211 luid
= (const LUID
*)id
.deviceLUID
;
212 trace("Device '%s', device UUID: %s, driver UUID: %s, device LUID: %08x:%08x.\n",
213 properties2
.properties
.deviceName
, wine_dbgstr_guid((const GUID
*)id
.deviceUUID
),
214 wine_dbgstr_guid((const GUID
*)id
.driverUUID
), luid
->HighPart
, luid
->LowPart
);
215 ok(id
.deviceLUIDValid
== VK_TRUE
, "Expected valid device LUID.\n");
216 /* If deviceLUIDValid is VK_TRUE, deviceNodeMask must contain exactly one bit according
217 * to the Vulkan specification */
218 ok(id
.deviceNodeMask
&& !(id
.deviceNodeMask
& (id
.deviceNodeMask
- 1)),
219 "Expect deviceNodeMask to have only one bit set, got %#x.\n", id
.deviceNodeMask
);
223 heap_free(vk_physical_devices
);
224 vkDestroyInstance(vk_instance
, NULL
);
227 static void enumerate_device_queues(VkPhysicalDevice vk_physical_device
)
229 VkPhysicalDeviceProperties device_properties
;
230 VkQueueFamilyProperties
*properties
;
233 vkGetPhysicalDeviceProperties(vk_physical_device
, &device_properties
);
235 vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device
, &count
, NULL
);
236 properties
= heap_calloc(count
, sizeof(*properties
));
237 ok(!!properties
, "Failed to allocate memory.\n");
238 vkGetPhysicalDeviceQueueFamilyProperties(vk_physical_device
, &count
, properties
);
240 for (i
= 0; i
< count
; ++i
)
242 trace("Device '%s', queue family %u: flags %#x count %u.\n",
243 device_properties
.deviceName
, i
, properties
[i
].queueFlags
, properties
[i
].queueCount
);
246 heap_free(properties
);
249 static void test_physical_device_groups(void)
251 PFN_vkEnumeratePhysicalDeviceGroupsKHR vkEnumeratePhysicalDeviceGroupsKHR
;
252 VkPhysicalDeviceGroupProperties
*properties
;
253 VkDeviceGroupDeviceCreateInfo group_info
;
254 VkInstance vk_instance
;
255 uint32_t i
, j
, count
;
259 static const char *extensions
[] =
261 VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME
,
264 if ((vr
= create_instance_skip(ARRAY_SIZE(extensions
), extensions
, &vk_instance
)) < 0)
266 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
268 vkEnumeratePhysicalDeviceGroupsKHR
269 = (void *)vkGetInstanceProcAddr(vk_instance
, "vkEnumeratePhysicalDeviceGroupsKHR");
270 ok(!!vkEnumeratePhysicalDeviceGroupsKHR
, "Failed to get proc addr.\n");
272 vr
= vkEnumeratePhysicalDeviceGroupsKHR(vk_instance
, &count
, NULL
);
273 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
274 ok(count
> 0, "Unexpected device group count %u.\n", count
);
276 properties
= heap_calloc(count
, sizeof(*properties
));
277 ok(!!properties
, "Failed to allocate memory.\n");
278 vr
= vkEnumeratePhysicalDeviceGroupsKHR(vk_instance
, &count
, properties
);
279 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
281 for (i
= 0; i
< count
; ++i
)
283 trace("Group[%u] count %u, subset allocation %#x\n",
284 i
, properties
[i
].physicalDeviceCount
, properties
[i
].subsetAllocation
);
285 for (j
= 0; j
< properties
[i
].physicalDeviceCount
; ++j
)
286 enumerate_physical_device(properties
[i
].physicalDevices
[j
]);
289 if ((vr
= create_device(properties
->physicalDevices
[0], 0, NULL
, NULL
, &vk_device
)) < 0)
291 skip("Failed to create device, vr %d.\n", vr
);
294 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
295 vkDestroyDevice(vk_device
, NULL
);
297 group_info
.sType
= VK_STRUCTURE_TYPE_DEVICE_GROUP_DEVICE_CREATE_INFO
;
298 group_info
.pNext
= NULL
;
299 group_info
.physicalDeviceCount
= properties
->physicalDeviceCount
;
300 group_info
.pPhysicalDevices
= properties
->physicalDevices
;
301 vr
= create_device(group_info
.pPhysicalDevices
[0], 0, NULL
, &group_info
, &vk_device
);
302 ok(vr
== VK_SUCCESS
, "Failed to create device, VkResult %d.\n", vr
);
303 vkDestroyDevice(vk_device
, NULL
);
305 heap_free(properties
);
307 vkDestroyInstance(vk_instance
, NULL
);
310 static void test_destroy_command_pool(VkPhysicalDevice vk_physical_device
)
312 VkCommandBufferAllocateInfo allocate_info
;
313 VkCommandPoolCreateInfo pool_info
;
314 VkCommandBuffer vk_cmd_buffers
[4];
315 uint32_t queue_family_index
;
316 VkCommandPool vk_cmd_pool
;
320 if ((vr
= create_device(vk_physical_device
, 0, NULL
, NULL
, &vk_device
)) < 0)
322 skip("Failed to create device, vr %d.\n", vr
);
326 find_queue_family(vk_physical_device
, VK_QUEUE_GRAPHICS_BIT
, &queue_family_index
);
328 pool_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO
;
329 pool_info
.pNext
= NULL
;
331 pool_info
.queueFamilyIndex
= queue_family_index
;
332 vr
= vkCreateCommandPool(vk_device
, &pool_info
, NULL
, &vk_cmd_pool
);
333 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
335 allocate_info
.sType
= VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO
;
336 allocate_info
.pNext
= NULL
;
337 allocate_info
.commandPool
= vk_cmd_pool
;
338 allocate_info
.level
= VK_COMMAND_BUFFER_LEVEL_PRIMARY
;
339 allocate_info
.commandBufferCount
= ARRAY_SIZE(vk_cmd_buffers
);
340 vr
= vkAllocateCommandBuffers(vk_device
, &allocate_info
, vk_cmd_buffers
);
341 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
343 vkDestroyCommandPool(vk_device
, vk_cmd_pool
, NULL
);
344 vkDestroyCommandPool(vk_device
, VK_NULL_HANDLE
, NULL
);
346 vkDestroyDevice(vk_device
, NULL
);
349 static void test_unsupported_instance_extensions(void)
351 VkInstance vk_instance
;
355 static const char *extensions
[] =
357 "VK_KHR_xcb_surface",
358 "VK_KHR_xlib_surface",
361 for (i
= 0; i
< ARRAY_SIZE(extensions
); ++i
)
363 vr
= create_instance(1, &extensions
[i
], &vk_instance
);
364 ok(vr
== VK_ERROR_EXTENSION_NOT_PRESENT
,
365 "Got VkResult %d for extension %s.\n", vr
, extensions
[i
]);
369 static void test_unsupported_device_extensions(VkPhysicalDevice vk_physical_device
)
375 static const char *extensions
[] =
377 "VK_KHR_external_fence_fd",
378 "VK_KHR_external_memory_fd",
379 "VK_KHR_external_semaphore_fd",
382 for (i
= 0; i
< ARRAY_SIZE(extensions
); ++i
)
384 vr
= create_device(vk_physical_device
, 1, &extensions
[i
], NULL
, &vk_device
);
385 ok(vr
== VK_ERROR_EXTENSION_NOT_PRESENT
,
386 "Got VkResult %d for extension %s.\n", vr
, extensions
[i
]);
390 static void test_private_data(VkPhysicalDevice vk_physical_device
)
392 PFN_vkDestroyPrivateDataSlotEXT pfn_vkDestroyPrivateDataSlotEXT
;
393 PFN_vkCreatePrivateDataSlotEXT pfn_vkCreatePrivateDataSlotEXT
;
394 VkPrivateDataSlotCreateInfoEXT data_create_info
;
395 PFN_vkGetPrivateDataEXT pfn_vkGetPrivateDataEXT
;
396 PFN_vkSetPrivateDataEXT pfn_vkSetPrivateDataEXT
;
397 VkPrivateDataSlotEXT data_slot
;
402 static const uint64_t data_value
= 0x70AD;
404 static const char *ext_name
= "VK_EXT_private_data";
406 if ((vr
= create_device(vk_physical_device
, 1, &ext_name
, NULL
, &vk_device
)) < 0)
408 skip("Failed to create device with VK_EXT_private_data, VkResult %d.\n", vr
);
412 pfn_vkDestroyPrivateDataSlotEXT
=
413 (void*) vkGetDeviceProcAddr(vk_device
, "vkDestroyPrivateDataSlotEXT");
414 pfn_vkCreatePrivateDataSlotEXT
=
415 (void*) vkGetDeviceProcAddr(vk_device
, "vkCreatePrivateDataSlotEXT");
416 pfn_vkGetPrivateDataEXT
=
417 (void*) vkGetDeviceProcAddr(vk_device
, "vkGetPrivateDataEXT");
418 pfn_vkSetPrivateDataEXT
=
419 (void*) vkGetDeviceProcAddr(vk_device
, "vkSetPrivateDataEXT");
421 data_create_info
.sType
= VK_STRUCTURE_TYPE_PRIVATE_DATA_SLOT_CREATE_INFO_EXT
;
422 data_create_info
.pNext
= NULL
;
423 data_create_info
.flags
= 0;
424 vr
= pfn_vkCreatePrivateDataSlotEXT(vk_device
, &data_create_info
, NULL
, &data_slot
);
425 ok(vr
== VK_SUCCESS
, "Failed to create private data slot, VkResult %d.\n", vr
);
427 vr
= pfn_vkSetPrivateDataEXT(vk_device
, VK_OBJECT_TYPE_DEVICE
,
428 (uint64_t) (uintptr_t) vk_device
, data_slot
, data_value
);
429 ok(vr
== VK_SUCCESS
, "Failed to set private data, VkResult %d.\n", vr
);
431 pfn_vkGetPrivateDataEXT(vk_device
, VK_OBJECT_TYPE_DEVICE
,
432 (uint64_t) (uintptr_t) vk_device
, data_slot
, &data
);
433 ok(data
== data_value
, "Got unexpected private data, %s.\n",
434 wine_dbgstr_longlong(data
));
436 pfn_vkDestroyPrivateDataSlotEXT(vk_device
, data_slot
, NULL
);
437 vkDestroyDevice(vk_device
, NULL
);
440 static void for_each_device(void (*test_func
)(VkPhysicalDevice
))
442 VkPhysicalDevice
*vk_physical_devices
;
443 VkInstance vk_instance
;
448 if ((vr
= create_instance_skip(0, NULL
, &vk_instance
)) < 0)
450 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
452 vr
= vkEnumeratePhysicalDevices(vk_instance
, &count
, NULL
);
455 skip("No physical devices. VkResult %d.\n", vr
);
456 vkDestroyInstance(vk_instance
, NULL
);
460 vk_physical_devices
= heap_calloc(count
, sizeof(*vk_physical_devices
));
461 ok(!!vk_physical_devices
, "Failed to allocate memory.\n");
462 vr
= vkEnumeratePhysicalDevices(vk_instance
, &count
, vk_physical_devices
);
463 ok(vr
== VK_SUCCESS
, "Got unexpected VkResult %d.\n", vr
);
465 for (i
= 0; i
< count
; ++i
)
466 test_func(vk_physical_devices
[i
]);
468 heap_free(vk_physical_devices
);
470 vkDestroyInstance(vk_instance
, NULL
);
475 test_instance_version();
476 for_each_device(enumerate_physical_device
);
477 test_enumerate_physical_device2();
478 for_each_device(enumerate_device_queues
);
479 test_physical_device_groups();
480 for_each_device(test_destroy_command_pool
);
481 test_unsupported_instance_extensions();
482 for_each_device(test_unsupported_device_extensions
);
483 for_each_device(test_private_data
);