1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2021 Intel Corporation 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "vk_instance.h" 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci#include "vk_alloc.h" 27bf215546Sopenharmony_ci#include "vk_common_entrypoints.h" 28bf215546Sopenharmony_ci#include "vk_dispatch_trampolines.h" 29bf215546Sopenharmony_ci#include "vk_log.h" 30bf215546Sopenharmony_ci#include "vk_util.h" 31bf215546Sopenharmony_ci#include "vk_debug_utils.h" 32bf215546Sopenharmony_ci 33bf215546Sopenharmony_ci#include "compiler/glsl_types.h" 34bf215546Sopenharmony_ci 35bf215546Sopenharmony_ci#define VERSION_IS_1_0(version) \ 36bf215546Sopenharmony_ci (VK_API_VERSION_MAJOR(version) == 1 && VK_API_VERSION_MINOR(version) == 0) 37bf215546Sopenharmony_ci 38bf215546Sopenharmony_ciVkResult 39bf215546Sopenharmony_civk_instance_init(struct vk_instance *instance, 40bf215546Sopenharmony_ci const struct vk_instance_extension_table *supported_extensions, 41bf215546Sopenharmony_ci const struct vk_instance_dispatch_table *dispatch_table, 42bf215546Sopenharmony_ci const VkInstanceCreateInfo *pCreateInfo, 43bf215546Sopenharmony_ci const VkAllocationCallbacks *alloc) 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci memset(instance, 0, sizeof(*instance)); 46bf215546Sopenharmony_ci vk_object_base_init(NULL, &instance->base, VK_OBJECT_TYPE_INSTANCE); 47bf215546Sopenharmony_ci instance->alloc = *alloc; 48bf215546Sopenharmony_ci 49bf215546Sopenharmony_ci /* VK_EXT_debug_utils */ 50bf215546Sopenharmony_ci /* These messengers will only be used during vkCreateInstance or 51bf215546Sopenharmony_ci * vkDestroyInstance calls. We do this first so that it's safe to use 52bf215546Sopenharmony_ci * vk_errorf and friends. 53bf215546Sopenharmony_ci */ 54bf215546Sopenharmony_ci list_inithead(&instance->debug_utils.instance_callbacks); 55bf215546Sopenharmony_ci vk_foreach_struct_const(ext, pCreateInfo->pNext) { 56bf215546Sopenharmony_ci if (ext->sType == 57bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT) { 58bf215546Sopenharmony_ci const VkDebugUtilsMessengerCreateInfoEXT *debugMessengerCreateInfo = 59bf215546Sopenharmony_ci (const VkDebugUtilsMessengerCreateInfoEXT *)ext; 60bf215546Sopenharmony_ci struct vk_debug_utils_messenger *messenger = 61bf215546Sopenharmony_ci vk_alloc2(alloc, alloc, sizeof(struct vk_debug_utils_messenger), 8, 62bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_OBJECT); 63bf215546Sopenharmony_ci 64bf215546Sopenharmony_ci if (!messenger) 65bf215546Sopenharmony_ci return vk_error(instance, VK_ERROR_OUT_OF_HOST_MEMORY); 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci vk_object_base_init(NULL, &messenger->base, 68bf215546Sopenharmony_ci VK_OBJECT_TYPE_DEBUG_UTILS_MESSENGER_EXT); 69bf215546Sopenharmony_ci 70bf215546Sopenharmony_ci messenger->alloc = *alloc; 71bf215546Sopenharmony_ci messenger->severity = debugMessengerCreateInfo->messageSeverity; 72bf215546Sopenharmony_ci messenger->type = debugMessengerCreateInfo->messageType; 73bf215546Sopenharmony_ci messenger->callback = debugMessengerCreateInfo->pfnUserCallback; 74bf215546Sopenharmony_ci messenger->data = debugMessengerCreateInfo->pUserData; 75bf215546Sopenharmony_ci 76bf215546Sopenharmony_ci list_addtail(&messenger->link, 77bf215546Sopenharmony_ci &instance->debug_utils.instance_callbacks); 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci } 80bf215546Sopenharmony_ci 81bf215546Sopenharmony_ci uint32_t instance_version = VK_API_VERSION_1_0; 82bf215546Sopenharmony_ci if (dispatch_table->EnumerateInstanceVersion) 83bf215546Sopenharmony_ci dispatch_table->EnumerateInstanceVersion(&instance_version); 84bf215546Sopenharmony_ci 85bf215546Sopenharmony_ci instance->app_info = (struct vk_app_info) { .api_version = 0 }; 86bf215546Sopenharmony_ci if (pCreateInfo->pApplicationInfo) { 87bf215546Sopenharmony_ci const VkApplicationInfo *app = pCreateInfo->pApplicationInfo; 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci instance->app_info.app_name = 90bf215546Sopenharmony_ci vk_strdup(&instance->alloc, app->pApplicationName, 91bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 92bf215546Sopenharmony_ci instance->app_info.app_version = app->applicationVersion; 93bf215546Sopenharmony_ci 94bf215546Sopenharmony_ci instance->app_info.engine_name = 95bf215546Sopenharmony_ci vk_strdup(&instance->alloc, app->pEngineName, 96bf215546Sopenharmony_ci VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); 97bf215546Sopenharmony_ci instance->app_info.engine_version = app->engineVersion; 98bf215546Sopenharmony_ci 99bf215546Sopenharmony_ci instance->app_info.api_version = app->apiVersion; 100bf215546Sopenharmony_ci } 101bf215546Sopenharmony_ci 102bf215546Sopenharmony_ci /* From the Vulkan 1.2.199 spec: 103bf215546Sopenharmony_ci * 104bf215546Sopenharmony_ci * "Note: 105bf215546Sopenharmony_ci * 106bf215546Sopenharmony_ci * Providing a NULL VkInstanceCreateInfo::pApplicationInfo or providing 107bf215546Sopenharmony_ci * an apiVersion of 0 is equivalent to providing an apiVersion of 108bf215546Sopenharmony_ci * VK_MAKE_API_VERSION(0,1,0,0)." 109bf215546Sopenharmony_ci */ 110bf215546Sopenharmony_ci if (instance->app_info.api_version == 0) 111bf215546Sopenharmony_ci instance->app_info.api_version = VK_API_VERSION_1_0; 112bf215546Sopenharmony_ci 113bf215546Sopenharmony_ci /* From the Vulkan 1.2.199 spec: 114bf215546Sopenharmony_ci * 115bf215546Sopenharmony_ci * VUID-VkApplicationInfo-apiVersion-04010 116bf215546Sopenharmony_ci * 117bf215546Sopenharmony_ci * "If apiVersion is not 0, then it must be greater than or equal to 118bf215546Sopenharmony_ci * VK_API_VERSION_1_0" 119bf215546Sopenharmony_ci */ 120bf215546Sopenharmony_ci assert(instance->app_info.api_version >= VK_API_VERSION_1_0); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci /* From the Vulkan 1.2.199 spec: 123bf215546Sopenharmony_ci * 124bf215546Sopenharmony_ci * "Vulkan 1.0 implementations were required to return 125bf215546Sopenharmony_ci * VK_ERROR_INCOMPATIBLE_DRIVER if apiVersion was larger than 1.0. 126bf215546Sopenharmony_ci * Implementations that support Vulkan 1.1 or later must not return 127bf215546Sopenharmony_ci * VK_ERROR_INCOMPATIBLE_DRIVER for any value of apiVersion." 128bf215546Sopenharmony_ci */ 129bf215546Sopenharmony_ci if (VERSION_IS_1_0(instance_version) && 130bf215546Sopenharmony_ci !VERSION_IS_1_0(instance->app_info.api_version)) 131bf215546Sopenharmony_ci return VK_ERROR_INCOMPATIBLE_DRIVER; 132bf215546Sopenharmony_ci 133bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->enabledExtensionCount; i++) { 134bf215546Sopenharmony_ci int idx; 135bf215546Sopenharmony_ci for (idx = 0; idx < VK_INSTANCE_EXTENSION_COUNT; idx++) { 136bf215546Sopenharmony_ci if (strcmp(pCreateInfo->ppEnabledExtensionNames[i], 137bf215546Sopenharmony_ci vk_instance_extensions[idx].extensionName) == 0) 138bf215546Sopenharmony_ci break; 139bf215546Sopenharmony_ci } 140bf215546Sopenharmony_ci 141bf215546Sopenharmony_ci if (idx >= VK_INSTANCE_EXTENSION_COUNT) 142bf215546Sopenharmony_ci return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT, 143bf215546Sopenharmony_ci "%s not supported", 144bf215546Sopenharmony_ci pCreateInfo->ppEnabledExtensionNames[i]); 145bf215546Sopenharmony_ci 146bf215546Sopenharmony_ci if (!supported_extensions->extensions[idx]) 147bf215546Sopenharmony_ci return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT, 148bf215546Sopenharmony_ci "%s not supported", 149bf215546Sopenharmony_ci pCreateInfo->ppEnabledExtensionNames[i]); 150bf215546Sopenharmony_ci 151bf215546Sopenharmony_ci#ifdef ANDROID 152bf215546Sopenharmony_ci if (!vk_android_allowed_instance_extensions.extensions[idx]) 153bf215546Sopenharmony_ci return vk_errorf(instance, VK_ERROR_EXTENSION_NOT_PRESENT, 154bf215546Sopenharmony_ci "%s not supported", 155bf215546Sopenharmony_ci pCreateInfo->ppEnabledExtensionNames[i]); 156bf215546Sopenharmony_ci#endif 157bf215546Sopenharmony_ci 158bf215546Sopenharmony_ci instance->enabled_extensions.extensions[idx] = true; 159bf215546Sopenharmony_ci } 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci instance->dispatch_table = *dispatch_table; 162bf215546Sopenharmony_ci 163bf215546Sopenharmony_ci /* Add common entrypoints without overwriting driver-provided ones. */ 164bf215546Sopenharmony_ci vk_instance_dispatch_table_from_entrypoints( 165bf215546Sopenharmony_ci &instance->dispatch_table, &vk_common_instance_entrypoints, false); 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci if (mtx_init(&instance->debug_report.callbacks_mutex, mtx_plain) != 0) 168bf215546Sopenharmony_ci return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED); 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci list_inithead(&instance->debug_report.callbacks); 171bf215546Sopenharmony_ci 172bf215546Sopenharmony_ci if (mtx_init(&instance->debug_utils.callbacks_mutex, mtx_plain) != 0) { 173bf215546Sopenharmony_ci mtx_destroy(&instance->debug_report.callbacks_mutex); 174bf215546Sopenharmony_ci return vk_error(instance, VK_ERROR_INITIALIZATION_FAILED); 175bf215546Sopenharmony_ci } 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci list_inithead(&instance->debug_utils.callbacks); 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci glsl_type_singleton_init_or_ref(); 180bf215546Sopenharmony_ci 181bf215546Sopenharmony_ci return VK_SUCCESS; 182bf215546Sopenharmony_ci} 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_civoid 185bf215546Sopenharmony_civk_instance_finish(struct vk_instance *instance) 186bf215546Sopenharmony_ci{ 187bf215546Sopenharmony_ci glsl_type_singleton_decref(); 188bf215546Sopenharmony_ci if (unlikely(!list_is_empty(&instance->debug_utils.callbacks))) { 189bf215546Sopenharmony_ci list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger, 190bf215546Sopenharmony_ci &instance->debug_utils.callbacks, link) { 191bf215546Sopenharmony_ci list_del(&messenger->link); 192bf215546Sopenharmony_ci vk_object_base_finish(&messenger->base); 193bf215546Sopenharmony_ci vk_free2(&instance->alloc, &messenger->alloc, messenger); 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci } 196bf215546Sopenharmony_ci if (unlikely(!list_is_empty(&instance->debug_utils.instance_callbacks))) { 197bf215546Sopenharmony_ci list_for_each_entry_safe(struct vk_debug_utils_messenger, messenger, 198bf215546Sopenharmony_ci &instance->debug_utils.instance_callbacks, 199bf215546Sopenharmony_ci link) { 200bf215546Sopenharmony_ci list_del(&messenger->link); 201bf215546Sopenharmony_ci vk_object_base_finish(&messenger->base); 202bf215546Sopenharmony_ci vk_free2(&instance->alloc, &messenger->alloc, messenger); 203bf215546Sopenharmony_ci } 204bf215546Sopenharmony_ci } 205bf215546Sopenharmony_ci mtx_destroy(&instance->debug_report.callbacks_mutex); 206bf215546Sopenharmony_ci mtx_destroy(&instance->debug_utils.callbacks_mutex); 207bf215546Sopenharmony_ci vk_free(&instance->alloc, (char *)instance->app_info.app_name); 208bf215546Sopenharmony_ci vk_free(&instance->alloc, (char *)instance->app_info.engine_name); 209bf215546Sopenharmony_ci vk_object_base_finish(&instance->base); 210bf215546Sopenharmony_ci} 211bf215546Sopenharmony_ci 212bf215546Sopenharmony_ciVkResult 213bf215546Sopenharmony_civk_enumerate_instance_extension_properties( 214bf215546Sopenharmony_ci const struct vk_instance_extension_table *supported_extensions, 215bf215546Sopenharmony_ci uint32_t *pPropertyCount, 216bf215546Sopenharmony_ci VkExtensionProperties *pProperties) 217bf215546Sopenharmony_ci{ 218bf215546Sopenharmony_ci VK_OUTARRAY_MAKE_TYPED(VkExtensionProperties, out, pProperties, pPropertyCount); 219bf215546Sopenharmony_ci 220bf215546Sopenharmony_ci for (int i = 0; i < VK_INSTANCE_EXTENSION_COUNT; i++) { 221bf215546Sopenharmony_ci if (!supported_extensions->extensions[i]) 222bf215546Sopenharmony_ci continue; 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci#ifdef ANDROID 225bf215546Sopenharmony_ci if (!vk_android_allowed_instance_extensions.extensions[i]) 226bf215546Sopenharmony_ci continue; 227bf215546Sopenharmony_ci#endif 228bf215546Sopenharmony_ci 229bf215546Sopenharmony_ci vk_outarray_append_typed(VkExtensionProperties, &out, prop) { 230bf215546Sopenharmony_ci *prop = vk_instance_extensions[i]; 231bf215546Sopenharmony_ci } 232bf215546Sopenharmony_ci } 233bf215546Sopenharmony_ci 234bf215546Sopenharmony_ci return vk_outarray_status(&out); 235bf215546Sopenharmony_ci} 236bf215546Sopenharmony_ci 237bf215546Sopenharmony_ciPFN_vkVoidFunction 238bf215546Sopenharmony_civk_instance_get_proc_addr(const struct vk_instance *instance, 239bf215546Sopenharmony_ci const struct vk_instance_entrypoint_table *entrypoints, 240bf215546Sopenharmony_ci const char *name) 241bf215546Sopenharmony_ci{ 242bf215546Sopenharmony_ci PFN_vkVoidFunction func; 243bf215546Sopenharmony_ci 244bf215546Sopenharmony_ci /* The Vulkan 1.0 spec for vkGetInstanceProcAddr has a table of exactly 245bf215546Sopenharmony_ci * when we have to return valid function pointers, NULL, or it's left 246bf215546Sopenharmony_ci * undefined. See the table for exact details. 247bf215546Sopenharmony_ci */ 248bf215546Sopenharmony_ci if (name == NULL) 249bf215546Sopenharmony_ci return NULL; 250bf215546Sopenharmony_ci 251bf215546Sopenharmony_ci#define LOOKUP_VK_ENTRYPOINT(entrypoint) \ 252bf215546Sopenharmony_ci if (strcmp(name, "vk" #entrypoint) == 0) \ 253bf215546Sopenharmony_ci return (PFN_vkVoidFunction)entrypoints->entrypoint 254bf215546Sopenharmony_ci 255bf215546Sopenharmony_ci LOOKUP_VK_ENTRYPOINT(EnumerateInstanceExtensionProperties); 256bf215546Sopenharmony_ci LOOKUP_VK_ENTRYPOINT(EnumerateInstanceLayerProperties); 257bf215546Sopenharmony_ci LOOKUP_VK_ENTRYPOINT(EnumerateInstanceVersion); 258bf215546Sopenharmony_ci LOOKUP_VK_ENTRYPOINT(CreateInstance); 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_ci /* GetInstanceProcAddr() can also be called with a NULL instance. 261bf215546Sopenharmony_ci * See https://gitlab.khronos.org/vulkan/vulkan/issues/2057 262bf215546Sopenharmony_ci */ 263bf215546Sopenharmony_ci LOOKUP_VK_ENTRYPOINT(GetInstanceProcAddr); 264bf215546Sopenharmony_ci 265bf215546Sopenharmony_ci#undef LOOKUP_VK_ENTRYPOINT 266bf215546Sopenharmony_ci 267bf215546Sopenharmony_ci if (instance == NULL) 268bf215546Sopenharmony_ci return NULL; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci func = vk_instance_dispatch_table_get_if_supported(&instance->dispatch_table, 271bf215546Sopenharmony_ci name, 272bf215546Sopenharmony_ci instance->app_info.api_version, 273bf215546Sopenharmony_ci &instance->enabled_extensions); 274bf215546Sopenharmony_ci if (func != NULL) 275bf215546Sopenharmony_ci return func; 276bf215546Sopenharmony_ci 277bf215546Sopenharmony_ci func = vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines, 278bf215546Sopenharmony_ci name, 279bf215546Sopenharmony_ci instance->app_info.api_version, 280bf215546Sopenharmony_ci &instance->enabled_extensions); 281bf215546Sopenharmony_ci if (func != NULL) 282bf215546Sopenharmony_ci return func; 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci func = vk_device_dispatch_table_get_if_supported(&vk_device_trampolines, 285bf215546Sopenharmony_ci name, 286bf215546Sopenharmony_ci instance->app_info.api_version, 287bf215546Sopenharmony_ci &instance->enabled_extensions, 288bf215546Sopenharmony_ci NULL); 289bf215546Sopenharmony_ci if (func != NULL) 290bf215546Sopenharmony_ci return func; 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci return NULL; 293bf215546Sopenharmony_ci} 294bf215546Sopenharmony_ci 295bf215546Sopenharmony_ciPFN_vkVoidFunction 296bf215546Sopenharmony_civk_instance_get_proc_addr_unchecked(const struct vk_instance *instance, 297bf215546Sopenharmony_ci const char *name) 298bf215546Sopenharmony_ci{ 299bf215546Sopenharmony_ci PFN_vkVoidFunction func; 300bf215546Sopenharmony_ci 301bf215546Sopenharmony_ci if (instance == NULL || name == NULL) 302bf215546Sopenharmony_ci return NULL; 303bf215546Sopenharmony_ci 304bf215546Sopenharmony_ci func = vk_instance_dispatch_table_get(&instance->dispatch_table, name); 305bf215546Sopenharmony_ci if (func != NULL) 306bf215546Sopenharmony_ci return func; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci func = vk_physical_device_dispatch_table_get( 309bf215546Sopenharmony_ci &vk_physical_device_trampolines, name); 310bf215546Sopenharmony_ci if (func != NULL) 311bf215546Sopenharmony_ci return func; 312bf215546Sopenharmony_ci 313bf215546Sopenharmony_ci func = vk_device_dispatch_table_get(&vk_device_trampolines, name); 314bf215546Sopenharmony_ci if (func != NULL) 315bf215546Sopenharmony_ci return func; 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci return NULL; 318bf215546Sopenharmony_ci} 319bf215546Sopenharmony_ci 320bf215546Sopenharmony_ciPFN_vkVoidFunction 321bf215546Sopenharmony_civk_instance_get_physical_device_proc_addr(const struct vk_instance *instance, 322bf215546Sopenharmony_ci const char *name) 323bf215546Sopenharmony_ci{ 324bf215546Sopenharmony_ci if (instance == NULL || name == NULL) 325bf215546Sopenharmony_ci return NULL; 326bf215546Sopenharmony_ci 327bf215546Sopenharmony_ci return vk_physical_device_dispatch_table_get_if_supported(&vk_physical_device_trampolines, 328bf215546Sopenharmony_ci name, 329bf215546Sopenharmony_ci instance->app_info.api_version, 330bf215546Sopenharmony_ci &instance->enabled_extensions); 331bf215546Sopenharmony_ci} 332