1 /*
2 * Copyright © 2021 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include "vk_instance.h"
25
26 #include "util/libdrm.h"
27 #include "util/perf/cpu_trace.h"
28
29 #include "vk_alloc.h"
30 #include "vk_common_entrypoints.h"
31 #include "vk_dispatch_trampolines.h"
32 #include "vk_log.h"
33 #include "vk_util.h"
34 #include "vk_debug_utils.h"
35 #include "vk_physical_device.h"
36
37 #ifndef VK_NO_NIR
38 #include "compiler/glsl_types.h"
39 #endif
40
41 #define VERSION_IS_1_0(version) \
42 (VK_API_VERSION_MAJOR(version) == 1 && VK_API_VERSION_MINOR(version) == 0)
43
44 static const struct debug_control trace_options[] = {
45 {"rmv", VK_TRACE_MODE_RMV},
46 {NULL, 0},
47 };
48
49 VkResult
vk_instance_init(struct vk_instance * instance,const struct vk_instance_extension_table * supported_extensions,const struct vk_instance_dispatch_table * dispatch_table,const VkInstanceCreateInfo * pCreateInfo,const VkAllocationCallbacks * alloc)50 vk_instance_init(struct vk_instance *instance,
51 const struct vk_instance_extension_table *supported_extensions,
52 const struct vk_instance_dispatch_table *dispatch_table,
53 const VkInstanceCreateInfo *pCreateInfo,
54 const VkAllocationCallbacks *alloc)
55 {
56 memset(instance, 0, sizeof(*instance));
57 vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE);
58 instance->alloc = *alloc;
59
60 util_cpu_trace_init();
61
62 /* VK_EXT_debug_utils */
63 /* These messengers will only be used during vkCreateInstance or
64 * vkDestroyInstance calls. We do this first so that it's safe to use
65 * vk_errorf and friends.
66 */
67 list_inithead(&instance->debug_utils.instance_callbacks);
68 vk_foreach_struct_const(ext, pCreateInfo->pNext) {
69 if (ext->sType ==
70 VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) {
71 const VkDebugUtilsMessengerCreateInfoEXT *debugMessengerCreateInfo =
72 (const VkDebugUtilsMessengerCreateInfoEXT *)ext;
73 struct vk_debug_utils_messenger *messenger =
74 vk_alloc2(alloc, alloc, sizeof(struct vk_debug_utils_messenger), 8,
75 VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
76
77 if (!messenger)
78 return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY);
79
80 vk_object_base_init(NULL, &messenger->base,
81 VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT);
82
83 messenger->alloc = *alloc;
84 messenger->severity = debugMessengerCreateInfo->messageSeverity;
85 messenger->type = debugMessengerCreateInfo->messageType;
86 messenger->callback = debugMessengerCreateInfo->pfnUserCallback;
87 messenger->data = debugMessengerCreateInfo->pUserData;
88
89 list_addtail(&messenger->link,
90 &instance->debug_utils.instance_callbacks);
91 }
92 }
93
94 uint32_t instance_version = VK_API_VERSION_1_0;
95 if (dispatch_table->EnumerateInstanceVersion)
96 dispatch_table->EnumerateInstanceVersion(&instance_version);
97
98 instance->app_info = (struct vk_app_info) { .api_version = 0 };
99 if (pCreateInfo->pApplicationInfo) {
100 const VkApplicationInfo *app = pCreateInfo->pApplicationInfo;
101
102 instance->app_info.app_name =
103 vk_strdup(&instance->alloc, app->pApplicationName,
104 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
105 instance->app_info.app_version = app->applicationVersion;
106
107 instance->app_info.engine_name =
108 vk_strdup(&instance->alloc, app->pEngineName,
109 VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
110 instance->app_info.engine_version = app->engineVersion;
111
112 instance->app_info.api_version = app->apiVersion;
113 }
114
115 /* From the Vulkan 1.2.199 spec:
116 *
117 * "Note:
118 *
119 * Providing a NULL VkInstanceCreateInfo::pApplicationInfo or providing
120 * an apiVersion of 0 is equivalent to providing an apiVersion of
121 * VK_MAKE_API_VERSION(0,1,0,0)."
122 */
123 if (instance->app_info.api_version == 0)
124 instance->app_info.api_version = VK_API_VERSION_1_0;
125
126 /* From the Vulkan 1.2.199 spec:
127 *
128 * VUID-VkApplicationInfo-apiVersion-04010
129 *
130 * "If apiVersion is not 0, then it must be greater than or equal to
131 * VK_API_VERSION_1_0"
132 */
133 assert(instance->app_info.api_version >= VK_API_VERSION_1_0);
134
135 /* From the Vulkan 1.2.199 spec:
136 *
137 * "Vulkan 1.0 implementations were required to return
138 * VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0.
139 * Implementations that support Vulkan 1.1 or later must not return
140 * VK_ERROR_INCOMPATIBLE_DRIVER for any value of apiVersion."
141 */
142 if (VERSION_IS_1_0(instance_version) &&
143 !VERSION_IS_1_0(instance->app_info.api_version))
144 return VK_ERROR_INCOMPATIBLE_DRIVER;
145
146 instance->supported_extensions = supported_extensions;
147
148 for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
149 int idx;
150 for (idx = 0; idx < VK_INSTANCE_EXTENSION_COUNT; idx++) {
151 if (strcmp(pCreateInfo->ppEnabledExtensionNames[i],
152 vk_instance_extensions[idx].extensionName) == 0)
153 break;
154 }
155
156 if (idx >= VK_INSTANCE_EXTENSION_COUNT)
157 return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
158 "%s not supported",
159 pCreateInfo->ppEnabledExtensionNames[i]);
160
161 if (!supported_extensions->extensions[idx])
162 return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
163 "%s not supported",
164 pCreateInfo->ppEnabledExtensionNames[i]);
165
166 #ifdef ANDROID
167 if (!vk_android_allowed_instance_extensions.extensions[idx])
168 return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT,
169 "%s not supported",
170 pCreateInfo->ppEnabledExtensionNames[i]);
171 #endif
172
173 instance->enabled_extensions.extensions[idx] = true;
174 }
175
176 instance->dispatch_table = *dispatch_table;
177
178 /* Add common entrypoints without overwriting driver-provided ones. */
179 vk_instance_dispatch_table_from_entrypoints(
180 &instance->dispatch_table, &vk_common_instance_entrypoints, false);
181
182 if (mtx_init(&instance->debug_report.callbacks_mutex, mtx_plain) != 0)
183 return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
184
185 list_inithead(&instance->debug_report.callbacks);
186
187 if (mtx_init(&instance->debug_utils.callbacks_mutex, mtx_plain) != 0) {
188 mtx_destroy(&instance->debug_report.callbacks_mutex);
189 return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
190 }
191
192 list_inithead(&instance->debug_utils.callbacks);
193
194 list_inithead(&instance->physical_devices.list);
195
196 if (mtx_init(&instance->physical_devices.mutex, mtx_plain) != 0) {
197 mtx_destroy(&instance->debug_report.callbacks_mutex);
198 mtx_destroy(&instance->debug_utils.callbacks_mutex);
199 return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED);
200 }
201
202 instance->trace_mode = parse_debug_string(getenv("MESA_VK_TRACE"), trace_options);
203 instance->trace_frame = (uint32_t)debug_get_num_option("MESA_VK_TRACE_FRAME", 0xFFFFFFFF);
204 instance->trace_trigger_file = getenv("MESA_VK_TRACE_TRIGGER");
205
206 #ifndef VK_NO_NIR
207 glsl_type_singleton_init_or_ref();
208 #endif
209
210 return VK_SUCCESS;
211 }
212
213 static void
destroy_physical_devices(struct vk_instance * instance)214 destroy_physical_devices(struct vk_instance *instance)
215 {
216 list_for_each_entry_safe(struct vk_physical_device, pdevice,
217 &instance->physical_devices.list, link) {
218 list_del(&pdevice->link);
219 instance->physical_devices.destroy(pdevice);
220 }
221 }
222
223 void
vk_instance_finish(struct vk_instance * instance)224 vk_instance_finish(struct vk_instance *instance)
225 {
226 destroy_physical_devices(instance);
227
228 #ifndef VK_NO_NIR
229 glsl_type_singleton_decref();
230 #endif
231
232 if (unlikely(!list_is_empty(&instance->debug_utils.callbacks))) {
233 list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger,
234 &instance->debug_utils.callbacks, link) {
235 list_del(&messenger->link);
236 vk_object_base_finish(&messenger->base);
237 vk_free2(&instance->alloc, &messenger->alloc, messenger);
238 }
239 }
240 if (unlikely(!list_is_empty(&instance->debug_utils.instance_callbacks))) {
241 list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger,
242 &instance->debug_utils.instance_callbacks,
243 link) {
244 list_del(&messenger->link);
245 vk_object_base_finish(&messenger->base);
246 vk_free2(&instance->alloc, &messenger->alloc, messenger);
247 }
248 }
249 mtx_destroy(&instance->debug_report.callbacks_mutex);
250 mtx_destroy(&instance->debug_utils.callbacks_mutex);
251 mtx_destroy(&instance->physical_devices.mutex);
252 vk_free(&instance->alloc, (char *)instance->app_info.app_name);
253 vk_free(&instance->alloc, (char *)instance->app_info.engine_name);
254 vk_object_base_finish(&instance->base);
255 }
256
257 VkResult
vk_enumerate_instance_extension_properties(const struct vk_instance_extension_table * supported_extensions,uint32_t * pPropertyCount,VkExtensionProperties * pProperties)258 vk_enumerate_instance_extension_properties(
259 const struct vk_instance_extension_table *supported_extensions,
260 uint32_t *pPropertyCount,
261 VkExtensionProperties *pProperties)
262 {
263 VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount);
264
265 for (int i = 0; i < VK_INSTANCE_EXTENSION_COUNT; i++) {
266 if (!supported_extensions->extensions[i])
267 continue;
268
269 #ifdef ANDROID
270 if (!vk_android_allowed_instance_extensions.extensions[i])
271 continue;
272 #endif
273
274 vk_outarray_append_typed(VkExtensionProperties, &out, prop) {
275 *prop = vk_instance_extensions[i];
276 }
277 }
278
279 return vk_outarray_status(&out);
280 }
281
282 PFN_vkVoidFunction
vk_instance_get_proc_addr(const struct vk_instance * instance,const struct vk_instance_entrypoint_table * entrypoints,const char * name)283 vk_instance_get_proc_addr(const struct vk_instance *instance,
284 const struct vk_instance_entrypoint_table *entrypoints,
285 const char *name)
286 {
287 PFN_vkVoidFunction func;
288
289 /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly
290 * when we have to return valid function pointers, NULL, or it's left
291 * undefined. See the table for exact details.
292 */
293 if (name == NULL)
294 return NULL;
295
296 #define LOOKUP_VK_ENTRYPOINT(entrypoint) \
297 if (strcmp(name, "vk" #entrypoint) == 0) \
298 return (PFN_vkVoidFunction)entrypoints->entrypoint
299
300 LOOKUP_VK_ENTRYPOINT(EnumerateInstanceExtensionProperties);
301 LOOKUP_VK_ENTRYPOINT(EnumerateInstanceLayerProperties);
302 LOOKUP_VK_ENTRYPOINT(EnumerateInstanceVersion);
303 LOOKUP_VK_ENTRYPOINT(CreateInstance);
304
305 /* GetInstanceProcAddr() can also be called with a NULL instance.
306 * See https://gitlab.khronos.org/vulkan/vulkan/issues/2057
307 */
308 LOOKUP_VK_ENTRYPOINT(GetInstanceProcAddr);
309
310 #undef LOOKUP_VK_ENTRYPOINT
311
312 if (instance == NULL)
313 return NULL;
314
315 func = vk_instance_dispatch_table_get_if_supported(&instance->dispatch_table,
316 name,
317 instance->app_info.api_version,
318 &instance->enabled_extensions);
319 if (func != NULL)
320 return func;
321
322 func = vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines,
323 name,
324 instance->app_info.api_version,
325 &instance->enabled_extensions);
326 if (func != NULL)
327 return func;
328
329 func = vk_device_dispatch_table_get_if_supported(&vk_device_trampolines,
330 name,
331 instance->app_info.api_version,
332 &instance->enabled_extensions,
333 NULL);
334 if (func != NULL)
335 return func;
336
337 return NULL;
338 }
339
340 PFN_vkVoidFunction
vk_instance_get_proc_addr_unchecked(const struct vk_instance * instance,const char * name)341 vk_instance_get_proc_addr_unchecked(const struct vk_instance *instance,
342 const char *name)
343 {
344 PFN_vkVoidFunction func;
345
346 if (instance == NULL || name == NULL)
347 return NULL;
348
349 func = vk_instance_dispatch_table_get(&instance->dispatch_table, name);
350 if (func != NULL)
351 return func;
352
353 func = vk_physical_device_dispatch_table_get(
354 &vk_physical_device_trampolines, name);
355 if (func != NULL)
356 return func;
357
358 func = vk_device_dispatch_table_get(&vk_device_trampolines, name);
359 if (func != NULL)
360 return func;
361
362 return NULL;
363 }
364
365 PFN_vkVoidFunction
vk_instance_get_physical_device_proc_addr(const struct vk_instance * instance,const char * name)366 vk_instance_get_physical_device_proc_addr(const struct vk_instance *instance,
367 const char *name)
368 {
369 if (instance == NULL || name == NULL)
370 return NULL;
371
372 return vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines,
373 name,
374 instance->app_info.api_version,
375 &instance->enabled_extensions);
376 }
377
378 void
vk_instance_add_driver_trace_modes(struct vk_instance * instance,const struct debug_control * modes)379 vk_instance_add_driver_trace_modes(struct vk_instance *instance,
380 const struct debug_control *modes)
381 {
382 instance->trace_mode |= parse_debug_string(getenv("MESA_VK_TRACE"), modes);
383 }
384
385 static VkResult
enumerate_drm_physical_devices_locked(struct vk_instance * instance)386 enumerate_drm_physical_devices_locked(struct vk_instance *instance)
387 {
388 /* TODO: Check for more devices ? */
389 drmDevicePtr devices[8];
390 int max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
391
392 if (max_devices < 1)
393 return VK_SUCCESS;
394
395 VkResult result;
396 for (uint32_t i = 0; i < (uint32_t)max_devices; i++) {
397 struct vk_physical_device *pdevice;
398 result = instance->physical_devices.try_create_for_drm(instance, devices[i], &pdevice);
399
400 /* Incompatible DRM device, skip. */
401 if (result == VK_ERROR_INCOMPATIBLE_DRIVER) {
402 result = VK_SUCCESS;
403 continue;
404 }
405
406 /* Error creating the physical device, report the error. */
407 if (result != VK_SUCCESS)
408 break;
409
410 list_addtail(&pdevice->link, &instance->physical_devices.list);
411 }
412
413 drmFreeDevices(devices, max_devices);
414 return result;
415 }
416
417 static VkResult
enumerate_physical_devices_locked(struct vk_instance * instance)418 enumerate_physical_devices_locked(struct vk_instance *instance)
419 {
420 if (instance->physical_devices.enumerate) {
421 VkResult result = instance->physical_devices.enumerate(instance);
422 if (result != VK_ERROR_INCOMPATIBLE_DRIVER)
423 return result;
424 }
425
426 VkResult result = VK_SUCCESS;
427
428 if (instance->physical_devices.try_create_for_drm) {
429 result = enumerate_drm_physical_devices_locked(instance);
430 if (result != VK_SUCCESS) {
431 destroy_physical_devices(instance);
432 return result;
433 }
434 }
435
436 return result;
437 }
438
439 static VkResult
enumerate_physical_devices(struct vk_instance * instance)440 enumerate_physical_devices(struct vk_instance *instance)
441 {
442 VkResult result = VK_SUCCESS;
443
444 mtx_lock(&instance->physical_devices.mutex);
445 if (!instance->physical_devices.enumerated) {
446 result = enumerate_physical_devices_locked(instance);
447 if (result == VK_SUCCESS)
448 instance->physical_devices.enumerated = true;
449 }
450 mtx_unlock(&instance->physical_devices.mutex);
451
452 return result;
453 }
454
455 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_EnumeratePhysicalDevices(VkInstance _instance,uint32_t * pPhysicalDeviceCount,VkPhysicalDevice * pPhysicalDevices)456 vk_common_EnumeratePhysicalDevices(VkInstance _instance, uint32_t *pPhysicalDeviceCount,
457 VkPhysicalDevice *pPhysicalDevices)
458 {
459 VK_FROM_HANDLE(vk_instance, instance, _instance);
460 VK_OUTARRAY_MAKE_TYPED(VkPhysicalDevice, out, pPhysicalDevices, pPhysicalDeviceCount);
461
462 VkResult result = enumerate_physical_devices(instance);
463 if (result != VK_SUCCESS)
464 return result;
465
466 list_for_each_entry(struct vk_physical_device, pdevice,
467 &instance->physical_devices.list, link) {
468 vk_outarray_append_typed(VkPhysicalDevice, &out, element) {
469 *element = vk_physical_device_to_handle(pdevice);
470 }
471 }
472
473 return vk_outarray_status(&out);
474 }
475
476 VKAPI_ATTR VkResult VKAPI_CALL
vk_common_EnumeratePhysicalDeviceGroups(VkInstance _instance,uint32_t * pGroupCount,VkPhysicalDeviceGroupProperties * pGroupProperties)477 vk_common_EnumeratePhysicalDeviceGroups(VkInstance _instance, uint32_t *pGroupCount,
478 VkPhysicalDeviceGroupProperties *pGroupProperties)
479 {
480 VK_FROM_HANDLE(vk_instance, instance, _instance);
481 VK_OUTARRAY_MAKE_TYPED(VkPhysicalDeviceGroupProperties, out, pGroupProperties,
482 pGroupCount);
483
484 VkResult result = enumerate_physical_devices(instance);
485 if (result != VK_SUCCESS)
486 return result;
487
488 list_for_each_entry(struct vk_physical_device, pdevice,
489 &instance->physical_devices.list, link) {
490 vk_outarray_append_typed(VkPhysicalDeviceGroupProperties, &out, p) {
491 p->physicalDeviceCount = 1;
492 memset(p->physicalDevices, 0, sizeof(p->physicalDevices));
493 p->physicalDevices[0] = vk_physical_device_to_handle(pdevice);
494 p->subsetAllocation = false;
495 }
496 }
497
498 return vk_outarray_status(&out);
499 }
500