diff options
| -rw-r--r-- | layers/layers_msg.h | 82 | ||||
| -rw-r--r-- | layers/mem_tracker.cpp | 89 | ||||
| -rw-r--r-- | layers/param_checker.cpp | 41 | ||||
| -rw-r--r-- | loader/loader.c | 299 | ||||
| -rw-r--r-- | loader/loader.h | 26 | ||||
| -rw-r--r-- | loader/table_ops.h | 6 | ||||
| -rw-r--r-- | loader/trampoline.c | 33 | ||||
| -rwxr-xr-x | vk-layer-generate.py | 78 |
8 files changed, 472 insertions, 182 deletions
diff --git a/layers/layers_msg.h b/layers/layers_msg.h index 88208f9b..a5e90de3 100644 --- a/layers/layers_msg.h +++ b/layers/layers_msg.h @@ -62,6 +62,8 @@ static VkResult layer_create_msg_callback( pNewDbgFuncNode->msgFlags = msgFlags; pNewDbgFuncNode->pUserData = pUserData; pNewDbgFuncNode->pNext = g_pDbgFunctionHead; + + /* TODO: This should be a per-instance resource */ g_pDbgFunctionHead = pNewDbgFuncNode; } else { free(pNewDbgFuncNode); @@ -94,10 +96,27 @@ static VkResult layer_destroy_msg_callback( return result; } +static void* msg_callback_get_proc_addr( + const char *funcName) +{ + if (!g_DEBUG_REPORT) { + return NULL; + } + + if (!strcmp(funcName, "vkDbgCreateMsgCallback")) { + return (void *) vkDbgCreateMsgCallback; + } + if (!strcmp(funcName, "vkDbgDestroyMsgCallback")) { + return (void *) vkDbgDestroyMsgCallback; + } + + return NULL; +} + // Utility function to handle reporting // If callbacks are enabled, use them, otherwise use printf static void layerCbMsg( - VkFlags msgFlags, + VkFlags msgFlags, VkObjectType objectType, VkObject srcObject, size_t location, @@ -122,65 +141,4 @@ static void layerCbMsg( } pTrav = pTrav->pNext; } -#if 0 - if (g_debugAction & (VK_DBG_LAYER_ACTION_LOG_MSG | VK_DBG_LAYER_ACTION_CALLBACK)) { - if (msgFlags & VK_DBG_REPORT_ERROR_BIT) { - if (g_reportFlags <= VK_DBG_LAYER_LEVEL_ERROR) { - if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) { - fprintf(g_logFile, "{%s}ERROR : %s\n", pLayerPrefix, pMsg); - fflush(g_logFile); - } - if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) { - while (pTrav) { - pTrav->pfnMsgCallback(msgFlags, - objectType, srcObject, - location, - msgCode, - pLayerPrefix, - pMsg, - pTrav->pUserData); - pTrav = pTrav->pNext; - } - } - } - } - switch (msgType) { - case VK_DBG_REPORT_ERROR_BIT: - break; - case VK_DBG_MSG_WARNING: - if (g_reportFlags <= VK_DBG_LAYER_LEVEL_WARN) { - if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) - fprintf(g_logFile, "{%s}WARN : %s\n", pLayerPrefix, pMsg); - if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) - while (pTrav) { - pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData); - pTrav = pTrav->pNext; - } - } - break; - case VK_DBG_MSG_PERF_WARNING: - if (g_reportFlags <= VK_DBG_LAYER_LEVEL_PERF_WARN) { - if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) - fprintf(g_logFile, "{%s}PERF_WARN : %s\n", pLayerPrefix, pMsg); - if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) - while (pTrav) { - pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData); - pTrav = pTrav->pNext; - } - } - break; - default: - if (g_reportFlags <= VK_DBG_LAYER_LEVEL_INFO) { - if (g_debugAction & VK_DBG_LAYER_ACTION_LOG_MSG) - fprintf(g_logFile, "{%s}INFO : %s\n", pLayerPrefix, pMsg); - if (g_debugAction & VK_DBG_LAYER_ACTION_CALLBACK) - while (pTrav) { - pTrav->pfnMsgCallback(msgType, validationLevel, srcObject, location, msgCode, pMsg, pTrav->pUserData); - pTrav = pTrav->pNext; - } - } - break; - } - } -#endif } diff --git a/layers/mem_tracker.cpp b/layers/mem_tracker.cpp index 3898a543..85af9c2b 100644 --- a/layers/mem_tracker.cpp +++ b/layers/mem_tracker.cpp @@ -863,6 +863,25 @@ VK_LAYER_EXPORT VkResult VKAPI vkDestroyInstance(VkInstance instance) return res; } +VkResult VKAPI vkCreateInstance( + const VkInstanceCreateInfo* pCreateInfo, + VkInstance* pInstance) +{ + loader_platform_thread_once(&g_initOnce, initMemTracker); + /* + * For layers, the pInstance has already been filled out + * by the loader so that dispatch table is available. + */ + initInstanceTable((const VkBaseLayerObject *) (*pInstance)); + + VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance); + + if (result == VK_SUCCESS) { + enable_debug_report(pCreateInfo->extensionCount, pCreateInfo->pEnabledExtensions); + } + return result; +} + VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice( VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, @@ -922,13 +941,19 @@ struct extProps { uint32_t version; const char * const name; }; -#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 1 +#define MEM_TRACKER_LAYER_EXT_ARRAY_SIZE 2 static const VkExtensionProperties mtExts[MEM_TRACKER_LAYER_EXT_ARRAY_SIZE] = { { VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES, "MemTracker", 0x10, - "Sample layer: MemTracker", + "Validation layer: MemTracker", + }, + { + VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES, + "Validation", + 0x10, + "Validation layer: MemTracker", } }; @@ -971,6 +996,45 @@ VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( return VK_SUCCESS; } +VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo( + VkPhysicalDevice physical_device, + VkExtensionInfoType infoType, + uint32_t extensionIndex, + size_t *pDataSize, + void *pData) +{ + uint32_t *count; + + if (pDataSize == NULL) { + return VK_ERROR_INVALID_POINTER; + } + + switch (infoType) { + case VK_EXTENSION_INFO_TYPE_COUNT: + *pDataSize = sizeof(uint32_t); + if (pData == NULL) { + return VK_SUCCESS; + } + count = (uint32_t *) pData; + *count = MEM_TRACKER_LAYER_EXT_ARRAY_SIZE; + break; + case VK_EXTENSION_INFO_TYPE_PROPERTIES: + *pDataSize = sizeof(VkExtensionProperties); + if (pData == NULL) { + return VK_SUCCESS; + } + if (extensionIndex >= MEM_TRACKER_LAYER_EXT_ARRAY_SIZE) { + return VK_ERROR_INVALID_VALUE; + } + memcpy((VkExtensionProperties *) pData, &mtExts[extensionIndex], sizeof(VkExtensionProperties)); + break; + default: + return VK_ERROR_INVALID_VALUE; + } + + return VK_SUCCESS; +} + VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue( VkDevice device, uint32_t queueNodeIndex, @@ -1252,6 +1316,10 @@ VK_LAYER_EXPORT VkResult VKAPI vkResetFences( uint32_t fenceCount, VkFence *pFences) { + /* + * TODO: Shouldn't we check for error conditions before passing down the chain? + * What if reason result is not VK_SUCCESS is something we could report as a validation error? + */ VkResult result = device_dispatch_table(device)->ResetFences(device, fenceCount, pFences); if (VK_SUCCESS == result) { loader_platform_thread_lock_mutex(&globalLock); @@ -2151,6 +2219,8 @@ VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr( VkDevice dev, const char *funcName) { + void *fptr; + if (dev == NULL) { return NULL; } @@ -2296,7 +2366,11 @@ VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr( return (void*) vkDestroySwapChainWSI; if (!strcmp(funcName, "vkGetSwapChainInfoWSI")) return (void*) vkGetSwapChainInfoWSI; - else + + fptr = msg_callback_get_proc_addr(funcName); + if (fptr) + return fptr; + { VkLayerDispatchTable **ppDisp = (VkLayerDispatchTable **) dev; VkLayerDispatchTable* pTable = tableMap[*ppDisp]; @@ -2310,6 +2384,7 @@ VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr( VkInstance instance, const char *funcName) { + void *fptr; if (instance == NULL) { return NULL; } @@ -2324,9 +2399,15 @@ VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr( if (!strcmp(funcName, "vkDestroyInstance")) return (void *) vkDestroyInstance; + if (!strcmp(funcName, "vkCreateInstance")) + return (void*) vkCreateInstance; if (!strcmp(funcName, "vkCreateDevice")) return (void*) vkCreateDevice; - else + + fptr = msg_callback_get_proc_addr(funcName); + if (fptr) + return fptr; + { VkLayerInstanceDispatchTable **ppDisp = (VkLayerInstanceDispatchTable **) instance; VkLayerInstanceDispatchTable* pTable = tableInstanceMap[*ppDisp]; diff --git a/layers/param_checker.cpp b/layers/param_checker.cpp index a27d54e0..fa8f316c 100644 --- a/layers/param_checker.cpp +++ b/layers/param_checker.cpp @@ -193,6 +193,10 @@ void PostCreateInstance(VkResult result, const VkInstanceCreateInfo *pCreateInfo VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance) { + /* TODO: shouldn't we have initInstanceDispatch here? */ + loader_platform_thread_once(&initOnce, initParamChecker); + initInstanceTable((const VkBaseLayerObject *) (*pInstance)); + PreCreateInstance(pCreateInfo->pAppInfo, pCreateInfo->pAllocCb); VkResult result = instance_dispatch_table(*pInstance)->CreateInstance(pCreateInfo, pInstance); PostCreateInstance(result, pCreateInfo, pInstance); @@ -327,13 +331,19 @@ VK_LAYER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device) return result; } -#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 1 +#define PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE 2 static const VkExtensionProperties pcExts[PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE] = { { VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES, "ParamChecker", 0x10, "Sample layer: ParamChecker", + }, + { + VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES, + "Validation", + 0x10, + "Sample layer: ParamChecker", } }; @@ -379,8 +389,33 @@ VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo( size_t* pDataSize, void* pData) { - VkResult result = instance_dispatch_table(gpu)->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData); - return result; + /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */ + uint32_t *count; + + if (pDataSize == NULL) + return VK_ERROR_INVALID_POINTER; + + switch (infoType) { + case VK_EXTENSION_INFO_TYPE_COUNT: + *pDataSize = sizeof(uint32_t); + if (pData == NULL) + return VK_SUCCESS; + count = (uint32_t *) pData; + *count = PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE; + break; + case VK_EXTENSION_INFO_TYPE_PROPERTIES: + *pDataSize = sizeof(VkExtensionProperties); + if (pData == NULL) + return VK_SUCCESS; + if (extensionIndex >= PARAM_CHECKER_LAYER_EXT_ARRAY_SIZE) + return VK_ERROR_INVALID_VALUE; + memcpy((VkExtensionProperties *) pData, &pcExts[extensionIndex], sizeof(VkExtensionProperties)); + break; + default: + return VK_ERROR_INVALID_VALUE; + }; + + return VK_SUCCESS; } VK_LAYER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue) diff --git a/loader/loader.c b/loader/loader.c index fd234657..b55ddcf8 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -69,7 +69,7 @@ VkLayerInstanceDispatchTable instance_disp = { .GetPhysicalDeviceInfo = loader_GetPhysicalDeviceInfo, .CreateDevice = loader_CreateDevice, .GetGlobalExtensionInfo = vkGetGlobalExtensionInfo, - .GetPhysicalDeviceExtensionInfo = loader_GetPhysicalDeviceExtensionInfo, + .GetPhysicalDeviceExtensionInfo = vkGetPhysicalDeviceExtensionInfo, .GetMultiDeviceCompatibility = loader_GetMultiDeviceCompatibility, .GetDisplayInfoWSI = loader_GetDisplayInfoWSI, .DbgCreateMsgCallback = loader_DbgCreateMsgCallback, @@ -302,6 +302,52 @@ static void get_global_extensions( return; } +static void get_physical_device_layer_extensions( + struct loader_instance *ptr_instance, + VkPhysicalDevice physical_device, + const uint32_t layer_index, + struct loader_extension_list *ext_list) +{ + uint32_t i, count; + size_t siz = sizeof(count); + VkResult res; + loader_platform_dl_handle lib_handle; + PFN_vkGetPhysicalDeviceExtensionInfo fp_get; + struct loader_extension_property ext_props; + + if (!loader.scanned_layers[layer_index].physical_device_extensions_supported) { + return; + } + + ext_props.origin = VK_EXTENSION_ORIGIN_LAYER; + ext_props.lib_name = loader.scanned_layers[layer_index].lib_name; + char funcStr[256]; + snprintf(funcStr, 256, "%sGetPhysicalDeviceExtensionInfo", ext_props.info.name); + lib_handle = loader_add_layer_lib("device", &ext_props); + fp_get = (PFN_vkGetPhysicalDeviceExtensionInfo) loader_platform_get_proc_address(lib_handle, "vkGetPhysicalDeviceExtensionInfo"); + if (fp_get) { + res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_COUNT, 0, &siz, &count); + if (res == VK_SUCCESS) { + siz = sizeof(VkExtensionProperties); + for (i = 0; i < count; i++) { + memset(&ext_props, 0, sizeof(ext_props)); + res = fp_get(physical_device, VK_EXTENSION_INFO_TYPE_PROPERTIES, i, &siz, &ext_props.info); + if (res == VK_SUCCESS && (ext_props.info.sType == VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES)) { + ext_props.hosted = false; + ext_props.origin = VK_EXTENSION_ORIGIN_LAYER; + ext_props.lib_name = loader.scanned_layers[layer_index].lib_name; + loader_add_to_ext_list(ext_list, 1, &ext_props); + } + } + } else { + loader_log(VK_DBG_REPORT_WARN_BIT, 0, "Error getting physical device extension info count from Layer %s", ext_props.lib_name); + } + } + + loader_remove_layer_lib(ptr_instance, &ext_props); + return; +} + static bool loader_init_ext_list(struct loader_extension_list *ext_info) { ext_info->capacity = 32 * sizeof(struct loader_extension_property); @@ -490,6 +536,7 @@ static void loader_scanned_icd_add(const char *filename) loader_platform_dl_handle handle; void *fp_create_inst; void *fp_get_global_ext_info; + void *fp_get_device_ext_info; struct loader_scanned_icds *new_node; // Used to call: dlopen(filename, RTLD_LAZY); @@ -509,6 +556,7 @@ static void loader_scanned_icd_add(const char *filename) LOOKUP(fp_create_inst, CreateInstance); LOOKUP(fp_get_global_ext_info, GetGlobalExtensionInfo); + LOOKUP(fp_get_device_ext_info, GetPhysicalDeviceExtensionInfo); #undef LOOKUP new_node = (struct loader_scanned_icds *) malloc(sizeof(struct loader_scanned_icds) @@ -522,6 +570,7 @@ static void loader_scanned_icd_add(const char *filename) new_node->CreateInstance = fp_create_inst; new_node->GetGlobalExtensionInfo = fp_get_global_ext_info; loader_init_ext_list(&new_node->global_extension_list); + loader_init_ext_list(&new_node->device_extension_list); new_node->next = loader.scanned_icd_list; new_node->lib_name = (char *) (new_node + 1); @@ -794,6 +843,12 @@ void layer_lib_scan(void) VK_EXTENSION_ORIGIN_LAYER, &loader.scanned_layers[count].global_extension_list); + fp_get_ext = loader_platform_get_proc_address(handle, + "vkGetPhysicalDeviceExtensionInfo"); + if (fp_get_ext) { + loader.scanned_layers[count].physical_device_extensions_supported = true; + } + count++; loader_platform_close_library(handle); } @@ -880,8 +935,8 @@ static loader_platform_dl_handle loader_add_layer_lib( /* Have already loaded this library, just increment ref count */ loader.loaded_layer_lib_list[i].ref_count++; loader_log(VK_DBG_REPORT_INFO_BIT, 0, - "Inserting %s layer %s from library %s", chain_type, - ext_prop->info.name, ext_prop->lib_name); + "%s Chain: Increment layer reference count for layer library %s", + chain_type, ext_prop->lib_name); return loader.loaded_layer_lib_list[i].lib_handle; } } @@ -896,7 +951,7 @@ static loader_platform_dl_handle loader_add_layer_lib( my_lib = &new_layer_lib_list[loader.loaded_layer_lib_count]; - /* NOTE: We require that the extension property to be immutable */ + /* NOTE: We require that the extension property be immutable */ my_lib->lib_name = ext_prop->lib_name; my_lib->ref_count = 0; my_lib->lib_handle = NULL; @@ -907,8 +962,8 @@ static loader_platform_dl_handle loader_add_layer_lib( return NULL; } else { loader_log(VK_DBG_REPORT_INFO_BIT, 0, - "Inserting %s layer %s from library %s", chain_type, - ext_prop->info.name, ext_prop->lib_name); + "Chain: %s: Loading layer library %s", + chain_type, ext_prop->lib_name); } loader.loaded_layer_lib_count++; loader.loaded_layer_lib_list = new_layer_lib_list; @@ -941,9 +996,15 @@ static void loader_remove_layer_lib( my_lib->ref_count--; inst->layer_count--; if (my_lib->ref_count > 0) { + loader_log(VK_DBG_REPORT_INFO_BIT, 0, + "Decrement reference count for layer library %s", ext_prop->lib_name); return; } + loader_platform_close_library(my_lib->lib_handle); + loader_log(VK_DBG_REPORT_INFO_BIT, 0, + "Unloading layer library %s", ext_prop->lib_name); + /* Need to remove unused library from list */ new_layer_lib_list = malloc((loader.loaded_layer_lib_count - 1) * sizeof(struct loader_lib_info)); if (!new_layer_lib_list) { @@ -961,6 +1022,7 @@ static void loader_remove_layer_lib( memcpy(&new_layer_lib_list[idx], &loader.loaded_layer_lib_list[idx+1], sizeof(struct loader_lib_info) * (loader.loaded_layer_lib_count - idx - 1)); } + free(loader.loaded_layer_lib_list); loader.loaded_layer_lib_count--; loader.loaded_layer_lib_list = new_layer_lib_list; @@ -1133,6 +1195,10 @@ uint32_t loader_activate_instance_layers(struct loader_instance *inst) continue; } + loader_log(VK_DBG_REPORT_INFO_BIT, 0, + "Insert instance layer library %s for extension: %s", + ext_prop->lib_name, ext_prop->info.name); + layer_idx--; } @@ -1141,6 +1207,14 @@ uint32_t loader_activate_instance_layers(struct loader_instance *inst) return inst->layer_count; } +void loader_activate_instance_layer_extensions(struct loader_instance *inst) +{ + + loader_init_instance_extension_dispatch_table(inst->disp, + inst->disp->GetInstanceProcAddr, + (VkInstance) inst->wrappedInstance); +} + void loader_enable_device_layers(struct loader_icd *icd, uint32_t gpu_index) { if (icd == NULL) @@ -1220,6 +1294,10 @@ extern uint32_t loader_activate_device_layers( continue; } + loader_log(VK_DBG_REPORT_INFO_BIT, 0, + "Insert device layer library %s for extension: %s", + ext_prop->lib_name, ext_prop->info.name); + layer_idx--; } @@ -1315,79 +1393,142 @@ VkResult loader_DestroyInstance( return VK_SUCCESS; } -VkResult loader_EnumeratePhysicalDevices( - VkInstance instance, - uint32_t* pPhysicalDeviceCount, - VkPhysicalDevice* pPhysicalDevices) +VkResult loader_init_physical_device_info( + struct loader_instance *ptr_instance) { - struct loader_instance *ptr_instance = (struct loader_instance *) instance; struct loader_icd *icd; uint32_t n, count = 0; VkResult res = VK_ERROR_UNKNOWN; - //in spirit of VK don't error check on the instance parameter icd = ptr_instance->icds; - if (pPhysicalDevices == NULL) { - while (icd) { - res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL); - if (res != VK_SUCCESS) - return res; - icd->gpu_count = n; - count += n; - icd = icd->next; - } + while (icd) { + res = icd->EnumeratePhysicalDevices(icd->instance, &n, NULL); + if (res != VK_SUCCESS) + return res; + icd->gpu_count = n; + count += n; + icd = icd->next; + } - ptr_instance->total_gpu_count = count; + ptr_instance->total_gpu_count = count; - } else - { - VkPhysicalDevice* gpus; - if (*pPhysicalDeviceCount < ptr_instance->total_gpu_count) - return VK_ERROR_INVALID_VALUE; - gpus = malloc( sizeof(VkPhysicalDevice) * *pPhysicalDeviceCount); - if (!gpus) - return VK_ERROR_OUT_OF_HOST_MEMORY; - while (icd) { - VkBaseLayerObject * wrapped_gpus; - PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr; - - n = *pPhysicalDeviceCount; - res = icd->EnumeratePhysicalDevices( - icd->instance, - &n, - gpus); - if (res == VK_SUCCESS && n) { - wrapped_gpus = (VkBaseLayerObject*) malloc(n * - sizeof(VkBaseLayerObject)); - icd->gpus = wrapped_gpus; - icd->gpu_count = n; - icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n * - sizeof(VkLayerDispatchTable)); - for (unsigned int i = 0; i < n; i++) { - (wrapped_gpus + i)->baseObject = gpus[i]; - (wrapped_gpus + i)->pGPA = get_proc_addr; - (wrapped_gpus + i)->nextObject = gpus[i]; - memcpy(pPhysicalDevices + count, gpus, sizeof(*pPhysicalDevices)); - loader_init_device_dispatch_table(icd->loader_dispatch + i, - get_proc_addr, gpus[i], gpus[i]); - - loader_init_dispatch(gpus[i], ptr_instance->disp); - } + VkPhysicalDevice* gpus; + gpus = malloc( sizeof(VkPhysicalDevice) * count); + if (!gpus) { + return VK_ERROR_OUT_OF_HOST_MEMORY; + } + + icd = ptr_instance->icds; + while (icd) { + VkBaseLayerObject * wrapped_gpus; + PFN_vkGetDeviceProcAddr get_proc_addr = icd->GetDeviceProcAddr; + + n = icd->gpu_count; + res = icd->EnumeratePhysicalDevices( + icd->instance, + &n, + gpus); + if (res == VK_SUCCESS && n) { + wrapped_gpus = (VkBaseLayerObject*) malloc(n * + sizeof(VkBaseLayerObject)); + if (!wrapped_gpus) { + /* TODO: Add cleanup code here */ + return VK_ERROR_OUT_OF_HOST_MEMORY; + } - count += n; + icd->gpus = wrapped_gpus; + icd->loader_dispatch = (VkLayerDispatchTable *) malloc(n * + sizeof(VkLayerDispatchTable)); + for (unsigned int i = 0; i < n; i++) { + (wrapped_gpus + i)->baseObject = gpus[i]; + (wrapped_gpus + i)->pGPA = get_proc_addr; + (wrapped_gpus + i)->nextObject = gpus[i]; - if (count >= *pPhysicalDeviceCount) { - break; + loader_init_device_dispatch_table(icd->loader_dispatch + i, + get_proc_addr, gpus[i], gpus[i]); + + loader_init_dispatch(gpus[i], ptr_instance->disp); + + if (!loader_init_ext_list(&icd->device_extension_cache[i])) { + /* TODO: Add cleanup code here */ + res = VK_ERROR_OUT_OF_HOST_MEMORY; + } + if (res == VK_SUCCESS && icd->GetPhysicalDeviceExtensionInfo) { + size_t data_size; + uint32_t extension_count; + + data_size = sizeof(extension_count); + res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_COUNT, 0, &data_size, &extension_count); + if (data_size == sizeof(extension_count) && res == VK_SUCCESS) { + struct loader_extension_property ext_props; + + /* Gather all the ICD extensions */ + for (uint32_t extension_id = 0; extension_id < extension_count; extension_id++) { + data_size = sizeof(VkExtensionProperties); + res = icd->GetPhysicalDeviceExtensionInfo(gpus[i], VK_EXTENSION_INFO_TYPE_PROPERTIES, + extension_id, &data_size, &ext_props.info); + if (data_size == sizeof(VkExtensionProperties) && res == VK_SUCCESS) { + ext_props.hosted = false; + ext_props.origin = VK_EXTENSION_ORIGIN_ICD; + ext_props.lib_name = icd->scanned_icds->lib_name; + loader_add_to_ext_list(&icd->device_extension_cache[i], 1, &ext_props); + } + } + + // Traverse layers list adding non-duplicate extensions to the list + for (uint32_t l = 0; l < loader.scanned_layer_count; l++) { + get_physical_device_layer_extensions(ptr_instance, gpus[i], l, &icd->device_extension_cache[i]); + } + } + } + + if (res != VK_SUCCESS) { + /* clean up any extension lists previously created before this request failed */ + for (uint32_t j = 0; j < i; j++) { + loader_destroy_ext_list(&icd->device_extension_cache[i]); + } + return res; } } - icd = icd->next; + count += n; } + + icd = icd->next; } - *pPhysicalDeviceCount = count; + return VK_SUCCESS; +} - return (count > 0) ? VK_SUCCESS : res; +VkResult loader_EnumeratePhysicalDevices( + VkInstance instance, + uint32_t* pPhysicalDeviceCount, + VkPhysicalDevice* pPhysicalDevices) +{ + uint32_t index = 0; + struct loader_instance *ptr_instance = (struct loader_instance *) instance; + struct loader_icd *icd = ptr_instance->icds; + + /* TODO: How do we only do this once? */ + if (ptr_instance->total_gpu_count == 0) { + loader_init_physical_device_info(ptr_instance); + } + + *pPhysicalDeviceCount = ptr_instance->total_gpu_count; + if (!pPhysicalDevices) { + return VK_SUCCESS; + } + + while (icd) { + assert((index + icd->gpu_count) <= *pPhysicalDeviceCount); + for (uint32_t i = 0; i < icd->gpu_count; i++) { + memcpy(&pPhysicalDevices[index], &icd->gpus[i].baseObject, sizeof(VkPhysicalDevice)); + } + index += icd->gpu_count; + icd = icd->next; + } + + return VK_SUCCESS; } VkResult loader_GetPhysicalDeviceInfo( @@ -1572,7 +1713,8 @@ LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( return VK_SUCCESS; } -VkResult loader_GetPhysicalDeviceExtensionInfo( + +LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo( VkPhysicalDevice gpu, VkExtensionInfoType infoType, uint32_t extensionIndex, @@ -1580,14 +1722,35 @@ VkResult loader_GetPhysicalDeviceExtensionInfo( void* pData) { uint32_t gpu_index; + uint32_t *count; struct loader_icd *icd = loader_get_icd((const VkBaseLayerObject *) gpu, &gpu_index); - VkResult res = VK_ERROR_INITIALIZATION_FAILED; - if (icd->GetPhysicalDeviceExtensionInfo) - res = icd->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, - pDataSize, pData); + if (pDataSize == NULL) + return VK_ERROR_INVALID_POINTER; - return res; + switch (infoType) { + case VK_EXTENSION_INFO_TYPE_COUNT: + *pDataSize = sizeof(uint32_t); + if (pData == NULL) + return VK_SUCCESS; + count = (uint32_t *) pData; + *count = icd->device_extension_cache[gpu_index].count; + break; + case VK_EXTENSION_INFO_TYPE_PROPERTIES: + *pDataSize = sizeof(VkExtensionProperties); + if (pData == NULL) + return VK_SUCCESS; + if (extensionIndex >= icd->device_extension_cache[gpu_index].count) + return VK_ERROR_INVALID_VALUE; + memcpy((VkExtensionProperties *) pData, + &icd->device_extension_cache[gpu_index].list[extensionIndex], + sizeof(VkExtensionProperties)); + break; + default: + return VK_ERROR_INVALID_VALUE; + }; + + return VK_SUCCESS; } VkResult loader_GetMultiDeviceCompatibility( diff --git a/loader/loader.h b/loader/loader.h index 8b427b5f..2d3b067a 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -69,16 +69,14 @@ struct loader_scanned_layers { char *lib_name; /* cache of global extensions for a specific layer */ -// uint32_t global_extension_count; -// struct loader_extension_property *global_extensions; struct loader_extension_list global_extension_list; + bool physical_device_extensions_supported; /* * cache of device extensions for a specific layer, * filled in at CreateInstance time */ - uint32_t device_ext_count; - struct loader_extension_property *device_ext_list; + struct loader_extension_list physical_device_extension_list; }; struct loader_icd { @@ -105,6 +103,13 @@ struct loader_icd { uint32_t app_extension_count[MAX_GPUS_FOR_LAYER]; VkExtensionProperties *app_extension_props[MAX_GPUS_FOR_LAYER]; + /* + * Fill in the cache of available extensions from all layers that + * operate with this physical device. + * This cache will be used to satisfy calls to GetPhysicalDeviceExtensionInfo + */ + struct loader_extension_list device_extension_cache[MAX_GPUS_FOR_LAYER]; + struct loader_extension_list enabled_device_extensions[MAX_GPUS_FOR_LAYER]; }; @@ -238,8 +243,7 @@ struct loader_scanned_icds { * cache of device extensions for specific ICD, * filled in at CreateInstance time */ - uint32_t device_extension_count; - struct loader_extension_property *device_extensions; + struct loader_extension_list device_extension_list; }; static inline void loader_set_dispatch(VkObject obj, const void *data) @@ -312,7 +316,6 @@ VkResult VKAPI loader_GetGlobalExtensionInfo( uint32_t extensionIndex, size_t* pDataSize, void* pData); -#endif VkResult loader_GetPhysicalDeviceExtensionInfo( VkPhysicalDevice gpu, @@ -320,6 +323,7 @@ VkResult loader_GetPhysicalDeviceExtensionInfo( uint32_t extensionIndex, size_t* pDataSize, void* pData); +#endif VkResult loader_GetMultiDeviceCompatibility( VkPhysicalDevice gpu0, @@ -343,7 +347,15 @@ void loader_icd_scan(void); void layer_lib_scan(void); void loader_coalesce_extensions(void); +static loader_platform_dl_handle loader_add_layer_lib( + const char *chain_type, + struct loader_extension_property *ext_prop); +static void loader_remove_layer_lib( + struct loader_instance *inst, + struct loader_extension_property *ext_prop); + struct loader_icd * loader_get_icd(const VkBaseLayerObject *gpu, uint32_t *gpu_index); uint32_t loader_activate_instance_layers(struct loader_instance *inst); +void loader_activate_instance_layer_extensions(struct loader_instance *inst); #endif /* LOADER_H */ diff --git a/loader/table_ops.h b/loader/table_ops.h index 93131b18..e4c39f2e 100644 --- a/loader/table_ops.h +++ b/loader/table_ops.h @@ -387,7 +387,13 @@ static inline void loader_init_instance_core_dispatch_table(VkLayerInstanceDispa table->GetPhysicalDeviceExtensionInfo = (PFN_vkGetPhysicalDeviceExtensionInfo) gpa(inst, "vkGetPhysicalDeviceExtensionInfo"); table->GetMultiDeviceCompatibility = (PFN_vkGetMultiDeviceCompatibility) gpa(inst, "vkGetMultiDeviceCompatibility"); table->GetDisplayInfoWSI = (PFN_vkGetDisplayInfoWSI) gpa(inst, "vkGetDisplayInfoWSI"); +} +static inline void loader_init_instance_extension_dispatch_table( + VkLayerInstanceDispatchTable *table, + PFN_vkGetInstanceProcAddr gpa, + VkInstance inst) +{ table->DbgCreateMsgCallback = (PFN_vkDbgCreateMsgCallback) gpa(inst, "vkDbgCreateMsgCallback"); table->DbgDestroyMsgCallback = (PFN_vkDbgDestroyMsgCallback) gpa(inst, "vkDbgDestroyMsgCallback"); } diff --git a/loader/trampoline.c b/loader/trampoline.c index 85039713..d22df048 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -120,6 +120,14 @@ LOADER_EXPORT VkResult VKAPI vkCreateInstance( res = ptr_instance->disp->CreateInstance(pCreateInfo, pInstance); + /* + * Finally have the layers in place and everyone has seen + * the CreateInstance command go by. This allows the layer's + * GetInstanceProcAddr functions to return valid extension functions + * if enabled. + */ + loader_activate_instance_layer_extensions(ptr_instance); + return res; } @@ -199,31 +207,6 @@ LOADER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device) return res; } -#if 0 //TODO get working on layer instance chain -LOADER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo( - VkExtensionInfoType infoType, - uint32_t extensionIndex, - size_t* pDataSize, - void* pData) -{ - return instance_disp.GetGlobalExtensionInfo(infoType, extensionIndex, pDataSize, pData); -} -#endif - -LOADER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo( - VkPhysicalDevice gpu, - VkExtensionInfoType infoType, - uint32_t extensionIndex, - size_t* pDataSize, - void* pData) -{ - const VkLayerInstanceDispatchTable *disp; - - disp = loader_get_instance_dispatch(gpu); - - return disp->GetPhysicalDeviceExtensionInfo(gpu, infoType, extensionIndex, pDataSize, pData); -} - LOADER_EXPORT VkResult VKAPI vkGetDeviceQueue(VkDevice device, uint32_t queueNodeIndex, uint32_t queueIndex, VkQueue* pQueue) { const VkLayerDispatchTable *disp; diff --git a/vk-layer-generate.py b/vk-layer-generate.py index c1d6fdc7..d3488f66 100755 --- a/vk-layer-generate.py +++ b/vk-layer-generate.py @@ -33,7 +33,7 @@ import vulkan import vk_helper def proto_is_global(proto): - if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetDisplayInfoWSI": + if proto.params[0].ty == "VkInstance" or proto.params[0].ty == "VkPhysicalDevice" or proto.name == "CreateInstance" or proto.name == "GetGlobalExtensionInfo" or proto.name == "GetPhysicalDeviceExtensionInfo" or proto.name == "GetDisplayInfoWSI": return True else: return False @@ -175,15 +175,32 @@ class Subcommand(object): def _gen_layer_get_global_extension_info(self, layer="Generic"): ggei_body = [] - ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1') - ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {') - ggei_body.append(' {') - ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,') - ggei_body.append(' "%s",' % layer) - ggei_body.append(' 0x10,') - ggei_body.append(' "layer: %s",' % layer) - ggei_body.append(' }') - ggei_body.append('};') + if layer == 'APIDump': + ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 1') + ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {') + ggei_body.append(' {') + ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,') + ggei_body.append(' "%s",' % layer) + ggei_body.append(' 0x10,') + ggei_body.append(' "layer: %s",' % layer) + ggei_body.append(' }') + ggei_body.append('};') + else: + ggei_body.append('#define LAYER_EXT_ARRAY_SIZE 2') + ggei_body.append('static const VkExtensionProperties layerExts[LAYER_EXT_ARRAY_SIZE] = {') + ggei_body.append(' {') + ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,') + ggei_body.append(' "%s",' % layer) + ggei_body.append(' 0x10,') + ggei_body.append(' "layer: %s",' % layer) + ggei_body.append(' },') + ggei_body.append(' {') + ggei_body.append(' VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,') + ggei_body.append(' "Validation",') + ggei_body.append(' 0x10,') + ggei_body.append(' "layer: %s",' % layer) + ggei_body.append(' }') + ggei_body.append('};') ggei_body.append('') ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)') ggei_body.append('{') @@ -215,6 +232,39 @@ class Subcommand(object): ggei_body.append('}') return "\n".join(ggei_body) + def _gen_layer_get_physical_device_extension_info(self, layer="Generic"): + ggei_body = [] + ggei_body.append('') + ggei_body.append('VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(VkPhysicalDevice physicalDevice, VkExtensionInfoType infoType, uint32_t extensionIndex, size_t* pDataSize, void* pData)') + ggei_body.append('{') + ggei_body.append(' uint32_t *count;') + ggei_body.append('') + ggei_body.append(' if (pDataSize == NULL)') + ggei_body.append(' return VK_ERROR_INVALID_POINTER;') + ggei_body.append('') + ggei_body.append(' switch (infoType) {') + ggei_body.append(' case VK_EXTENSION_INFO_TYPE_COUNT:') + ggei_body.append(' *pDataSize = sizeof(uint32_t);') + ggei_body.append(' if (pData == NULL)') + ggei_body.append(' return VK_SUCCESS;') + ggei_body.append(' count = (uint32_t *) pData;') + ggei_body.append(' *count = LAYER_EXT_ARRAY_SIZE;') + ggei_body.append(' break;') + ggei_body.append(' case VK_EXTENSION_INFO_TYPE_PROPERTIES:') + ggei_body.append(' *pDataSize = sizeof(VkExtensionProperties);') + ggei_body.append(' if (pData == NULL)') + ggei_body.append(' return VK_SUCCESS;') + ggei_body.append(' if (extensionIndex >= LAYER_EXT_ARRAY_SIZE)') + ggei_body.append(' return VK_ERROR_INVALID_VALUE;') + ggei_body.append(' memcpy((VkExtensionProperties *) pData, &layerExts[extensionIndex], sizeof(VkExtensionProperties));') + ggei_body.append(' break;') + ggei_body.append(' default:') + ggei_body.append(' return VK_ERROR_INVALID_VALUE;') + ggei_body.append(' };') + ggei_body.append(' return VK_SUCCESS;') + ggei_body.append('}') + return "\n".join(ggei_body) + def _generate_dispatch_entrypoints(self, qual=""): if qual: qual += " " @@ -236,6 +286,8 @@ class Subcommand(object): funcs.append('/* CreateDevice HERE */') elif 'GetGlobalExtensionInfo' == proto.name: intercept = self._gen_layer_get_global_extension_info(self.layer_name) + elif 'GetPhysicalDeviceExtensionInfo' == proto.name: + intercept = self._gen_layer_get_physical_device_extension_info(self.layer_name) if intercept is not None: funcs.append(intercept) intercepted.append(proto) @@ -538,7 +590,7 @@ class GenericLayerSubcommand(Subcommand): gen_header.append('}') return "\n".join(gen_header) def generate_intercept(self, proto, qual): - if proto.name in [ 'GetGlobalExtensionInfo' ]: + if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]: # use default version return None decl = proto.c_func(prefix="vk", attr="VKAPI") @@ -812,7 +864,7 @@ class APIDumpSubcommand(Subcommand): return "\n".join(func_body) def generate_intercept(self, proto, qual): - if proto.name in [ 'GetGlobalExtensionInfo']: + if proto.name in [ 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo']: return None decl = proto.c_func(prefix="vk", attr="VKAPI") ret_val = '' @@ -1250,7 +1302,7 @@ class ObjectTrackerSubcommand(Subcommand): return "\n".join(header_txt) def generate_intercept(self, proto, qual): - if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo' ]: + if proto.name in [ 'DbgCreateMsgCallback', 'GetGlobalExtensionInfo', 'GetPhysicalDeviceExtensionInfo' ]: # use default version return None |
