From 71a1e7e9a0afdfa207d8fe3d327be509c9821ae2 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Thu, 12 Jan 2017 12:27:19 -0700 Subject: [PATCH] loader: Modify EnumPhysDev functions Modify the loader's trampoline and terminator vkEnumeratePhysicalDevice functions to utilize helper functions. Also, fix the failure in CTS. Change-Id: Id9356fffd42f878c660ac8ee831e7527cce608bd --- loader/loader.c | 461 +++++++++++++++++++++++++++++++++------------------- loader/loader.h | 3 + loader/trampoline.c | 160 ++++-------------- 3 files changed, 326 insertions(+), 298 deletions(-) diff --git a/loader/loader.c b/loader/loader.c index 4179106..16bfced 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -803,6 +803,7 @@ static VkResult loader_add_instance_extensions( loader_log(inst, VK_DEBUG_REPORT_DEBUG_BIT_EXT, 0, "Instance Extension: %s (%s) version %s", ext_props[i].extensionName, lib_name, spec_version); + res = loader_add_to_ext_list(inst, ext_list, 1, &ext_props[i]); if (res != VK_SUCCESS) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, @@ -813,6 +814,7 @@ static VkResult loader_add_instance_extensions( } } } + out: return res; } @@ -1336,6 +1338,7 @@ VkResult loader_get_icd_loader_instance_extensions( } }; + // Traverse loader's extensions, adding non-duplicate extensions to the list debug_report_add_instance_extensions(inst, inst_exts); @@ -4393,6 +4396,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance( res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } + icd_create_info.enabledExtensionCount = 0; struct loader_extension_list icd_exts; @@ -4659,230 +4663,345 @@ out: return res; } -VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices( - VkInstance instance, uint32_t *pPhysicalDeviceCount, - VkPhysicalDevice *pPhysicalDevices) { - struct loader_instance *inst = (struct loader_instance *)instance; +VkResult setupLoaderTrampPhysDevs(VkInstance instance) { VkResult res = VK_SUCCESS; - struct loader_icd_term *icd_term = NULL; - struct loader_phys_dev_per_icd *icd_phys_devs = NULL; - uint32_t copy_count = 0; - uint32_t new_phys_dev_count = 0; - uint32_t i = 0; - struct loader_physical_device_term **new_phys_devs = NULL; + VkPhysicalDevice *local_phys_devs = NULL; + struct loader_instance *inst; + uint32_t total_count = 0; + struct loader_physical_device_tramp **new_phys_devs = NULL; - inst->total_gpu_count = 0; - icd_phys_devs = (struct loader_phys_dev_per_icd *)loader_stack_alloc( - sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); - if (NULL == icd_phys_devs) { + inst = loader_get_instance(instance); + if (NULL == inst) { + res = VK_ERROR_INITIALIZATION_FAILED; + goto out; + } + total_count = inst->total_gpu_count; + + // Create an array for the new physical devices, which will be stored + // in the instance for the trampoline code. + new_phys_devs = + (struct loader_physical_device_tramp **)loader_instance_heap_alloc( + inst, + total_count * sizeof(struct loader_physical_device_tramp *), + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == new_phys_devs) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices failed to allocate " - "temporary icd physical device array for %d ICDs", - inst->total_icd_count); + "setupLoaderTrampPhysDevs: Failed to new physical device " + "array of size %d", + total_count); res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } + memset(new_phys_devs, 0, + total_count * sizeof(struct loader_physical_device_tramp *)); - icd_term = inst->icd_terms; - for (i = 0; i < inst->total_icd_count; i++) { - if (NULL == icd_term) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "Invalid ICD encountered during" - "terminator_EnumeratePhysicalDevices"); - assert(false); - } + // Create a temporary array (on the stack) to keep track of the + // returned VkPhysicalDevice values. + local_phys_devs = + loader_stack_alloc(sizeof(VkPhysicalDevice) * total_count); + if (NULL == local_phys_devs) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTrampPhysDevs: Failed to allocate local " + "physical device array of size %d", + total_count); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memset(local_phys_devs, 0, sizeof(VkPhysicalDevice) * total_count); - // Determine how many physical devices are associated with this ICD. - res = icd_term->EnumeratePhysicalDevices(icd_term->instance, - &icd_phys_devs[i].count, NULL); - if (res != VK_SUCCESS) { - goto out; + res = inst->disp->EnumeratePhysicalDevices(instance, &total_count, + local_phys_devs); + if (VK_SUCCESS != res) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTrampPhysDevs: Failed during dispatch call " + "of \'vkEnumeratePhysicalDevices\' to lower layers or " + "loader."); + goto out; + } + + // Copy or create everything to fill the new array of physical devices + for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) { + + // Check if this physical device is already in the old buffer + for (uint32_t old_idx = 0; + old_idx < inst->phys_dev_count_tramp; + old_idx++) { + if (local_phys_devs[new_idx] == + inst->phys_devs_tramp[old_idx]->phys_dev) { + new_phys_devs[new_idx] = inst->phys_devs_tramp[old_idx]; + break; + } } - if (NULL != pPhysicalDevices) { - // Create an array to store each physical device for this ICD. - icd_phys_devs[i].phys_devs = (VkPhysicalDevice *)loader_stack_alloc( - icd_phys_devs[i].count * sizeof(VkPhysicalDevice)); - if (NULL == icd_phys_devs[i].phys_devs) { + // If this physical device isn't in the old buffer, create it + if (NULL == new_phys_devs[new_idx]) { + new_phys_devs[new_idx] = (struct loader_physical_device_tramp *) + loader_instance_heap_alloc( + inst, sizeof(struct loader_physical_device_tramp), + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == new_phys_devs[new_idx]) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices failed to " - "allocate temporary icd physical device storage for " - "ICD %d with %d phys devs.", - i, icd_phys_devs[i].count); + "setupLoaderTrampPhysDevs: Failed to allocate " + "physical device trampoline object %d", + new_idx); + total_count = new_idx; res = VK_ERROR_OUT_OF_HOST_MEMORY; goto out; } - // Query the VkPhysicalDevice values for each of the physical - // devices - // associated with this ICD. - res = icd_term->EnumeratePhysicalDevices( - icd_term->instance, &(icd_phys_devs[i].count), - icd_phys_devs[i].phys_devs); - if (res != VK_SUCCESS) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices: ICD Enumerate" - " call failed for ICD %d", - i); - goto out; + // Initialize the new physicalDevice object + loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp); + new_phys_devs[new_idx]->this_instance = inst; + new_phys_devs[new_idx]->phys_dev = local_phys_devs[new_idx]; + } + } + +out: + + if (VK_SUCCESS != res) { + if (NULL != new_phys_devs) { + for (uint32_t i = 0; i < total_count; i++) { + loader_instance_heap_free(inst, new_phys_devs[i]); } + loader_instance_heap_free(inst, new_phys_devs); + } + total_count = 0; + } else { + // Free everything that didn't carry over to the new array of + // physical devices + if (NULL != inst->phys_devs_tramp) { + for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) { + bool found = false; + for (uint32_t j = 0; j < total_count; j++) { + if (inst->phys_devs_tramp[i] == new_phys_devs[j]) { + found = true; + break; + } + } + if (!found) { + loader_instance_heap_free(inst, + inst->phys_devs_tramp[i]); + } + } + loader_instance_heap_free(inst, inst->phys_devs_tramp); + } + + // Swap in the new physical device list + inst->phys_dev_count_tramp = total_count; + inst->phys_devs_tramp = new_phys_devs; + } + + return res; +} + +VkResult setupLoaderTermPhysDevs(struct loader_instance *inst) { + VkResult res = VK_SUCCESS; + struct loader_icd_term *icd_term; + struct loader_phys_dev_per_icd *icd_phys_dev_array = NULL; + struct loader_physical_device_term **new_phys_devs = NULL; + uint32_t i = 0; + + inst->total_gpu_count = 0; + + // Allocate something to store the physical device characteristics + // that we read from each ICD. + icd_phys_dev_array = (struct loader_phys_dev_per_icd *)loader_stack_alloc( + sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); + if (NULL == icd_phys_dev_array) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Failed to allocate temporary " + " ICD Physical device info array of size %d", + inst->total_gpu_count); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memset(icd_phys_dev_array, 0, + sizeof(struct loader_phys_dev_per_icd) * inst->total_icd_count); + icd_term = inst->icd_terms; + + // For each ICD, query the number of physical devices, and then get an + // internal value for those physical devices. + while (NULL != icd_term) { + res = icd_term->EnumeratePhysicalDevices( + icd_term->instance, &icd_phys_dev_array[i].count, NULL); + if (VK_SUCCESS != res) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Call to " + "ICD %d's \'vkEnumeratePhysicalDevices\' failed with" + " error 0x%08x", + i, res); + goto out; + } - icd_phys_devs[i].this_icd_term = icd_term; + icd_phys_dev_array[i].phys_devs = + (VkPhysicalDevice *)loader_stack_alloc(icd_phys_dev_array[i].count * + sizeof(VkPhysicalDevice)); + if (NULL == icd_phys_dev_array[i].phys_devs) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Failed to allocate temporary " + " ICD Physical device array for ICD %d of size %d", + i, inst->total_gpu_count); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; } - inst->total_gpu_count += icd_phys_devs[i].count; + res = icd_term->EnumeratePhysicalDevices( + icd_term->instance, &(icd_phys_dev_array[i].count), + icd_phys_dev_array[i].phys_devs); + if (VK_SUCCESS != res) { + goto out; + } + inst->total_gpu_count += icd_phys_dev_array[i].count; + icd_phys_dev_array[i].this_icd_term = icd_term; - // Go to the next ICD icd_term = icd_term->next; + i++; } - if (inst->total_gpu_count == 0) { + if (0 == inst->total_gpu_count) { loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices: Determined 0 available" - "ICDs"); + "setupLoaderTermPhysDevs: Failed to detect any valid" + " GPUs in the current config"); res = VK_ERROR_INITIALIZATION_FAILED; goto out; } - copy_count = inst->total_gpu_count; - - if (NULL != pPhysicalDevices) { - new_phys_dev_count = inst->total_gpu_count; + new_phys_devs = loader_instance_heap_alloc( + inst, + sizeof(struct loader_physical_device_term *) * inst->total_gpu_count, + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); + if (NULL == new_phys_devs) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Failed to allocate new physical" + " device array of size %d", + inst->total_gpu_count); + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; + } + memset(new_phys_devs, 0, sizeof(struct loader_physical_device_term *) * + inst->total_gpu_count); - // Cap the number of devices at pPhysicalDeviceCount - if (copy_count > *pPhysicalDeviceCount) { - copy_count = *pPhysicalDeviceCount; - } + // Copy or create everything to fill the new array of physical devices + uint32_t idx = 0; + for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) { + for (uint32_t pd_idx = 0; pd_idx < icd_phys_dev_array[icd_idx].count; + pd_idx++) { - // Allocate the new devices list - new_phys_devs = loader_instance_heap_alloc( - inst, - sizeof(struct loader_physical_device_term *) * new_phys_dev_count, - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == new_phys_devs) { - loader_log( - inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices: Failed to allocate " - "new physical device array"); - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - memset(new_phys_devs, 0, - sizeof(struct loader_physical_device_term *) * - new_phys_dev_count); - - // Copy or create everything to fill the new array of physical devices - uint32_t idx = 0; - for (uint32_t icd_idx = 0; icd_idx < inst->total_icd_count; icd_idx++) { - for (uint32_t pd_idx = 0; pd_idx < icd_phys_devs[icd_idx].count; - pd_idx++) { - - // Check if this physical device is already in the old buffer - if (NULL != inst->phys_devs_term) { - for (uint32_t old_idx = 0; - old_idx < inst->phys_dev_count_term; - old_idx++) { - if (icd_phys_devs[icd_idx].phys_devs[pd_idx] == - inst->phys_devs_term[old_idx]->phys_dev) { - new_phys_devs[idx] = inst->phys_devs_term[old_idx]; - break; - } + // Check if this physical device is already in the old buffer + if (NULL != inst->phys_devs_term) { + for (uint32_t old_idx = 0; + old_idx < inst->phys_dev_count_term; + old_idx++) { + if (icd_phys_dev_array[icd_idx].phys_devs[pd_idx] == + inst->phys_devs_term[old_idx]->phys_dev) { + new_phys_devs[idx] = inst->phys_devs_term[old_idx]; + break; } } - // If this physical device isn't in the old buffer, then we - // need to create it. + } + // If this physical device isn't in the old buffer, then we + // need to create it. + if (NULL == new_phys_devs[idx]) { + new_phys_devs[idx] = loader_instance_heap_alloc( + inst, sizeof(struct loader_physical_device_term), + VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); if (NULL == new_phys_devs[idx]) { - new_phys_devs[idx] = loader_instance_heap_alloc( - inst, sizeof(struct loader_physical_device_term), - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == new_phys_devs[idx]) { - copy_count = idx; - loader_log( - inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "terminator_EnumeratePhysicalDevices: Failed " - " to create new physical device storage."); - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - - loader_set_dispatch((void *)new_phys_devs[idx], inst->disp); - new_phys_devs[idx]->this_icd_term = - icd_phys_devs[icd_idx].this_icd_term; - new_phys_devs[idx]->icd_index = (uint8_t)(icd_idx); - new_phys_devs[idx]->phys_dev = - icd_phys_devs[icd_idx].phys_devs[pd_idx]; + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "setupLoaderTermPhysDevs: Failed to allocate " + "physical device terminator object %d", + idx); + inst->total_gpu_count = idx; + res = VK_ERROR_OUT_OF_HOST_MEMORY; + goto out; } - // Copy wrapped object into application provided array - if (idx < copy_count) { - pPhysicalDevices[idx] = - (VkPhysicalDevice)new_phys_devs[idx]; - } - idx++; - if (idx >= new_phys_dev_count) { - break; - } - } - if (idx >= new_phys_dev_count) { - break; + loader_set_dispatch((void *)new_phys_devs[idx], inst->disp); + new_phys_devs[idx]->this_icd_term = + icd_phys_dev_array[icd_idx].this_icd_term; + new_phys_devs[idx]->icd_index = (uint8_t)(icd_idx); + new_phys_devs[idx]->phys_dev = + icd_phys_dev_array[icd_idx].phys_devs[pd_idx]; } + idx++; } } out: - if (NULL != pPhysicalDevices) { - // If there was no error, we still need to free the old buffer and - // assign the new one - if (res == VK_SUCCESS || res == VK_INCOMPLETE) { - // Free everything that didn't carry over to the new array of - // physical devices. Everything else will have been copied over - // to the new array. - if (NULL != inst->phys_devs_term) { - for (uint32_t cur_pd = 0; cur_pd < inst->phys_dev_count_term; - cur_pd++) { - bool found = false; - for (uint32_t new_pd_idx = 0; - new_pd_idx < new_phys_dev_count; - new_pd_idx++) { - if (inst->phys_devs_term[cur_pd] == - new_phys_devs[new_pd_idx]) { - found = true; - break; - } - } - if (!found) { - loader_instance_heap_free(inst, - inst->phys_devs_term[cur_pd]); + if (VK_SUCCESS != res) { + if (NULL != inst->phys_devs_term) { + // We've encountered an error, so we should free the + // new buffers. + for (uint32_t i = 0; i < inst->total_gpu_count; i++) { + loader_instance_heap_free(inst, new_phys_devs[i]); + } + loader_instance_heap_free(inst, inst->phys_devs_term); + inst->total_gpu_count = 0; + } + } else { + // Free everything that didn't carry over to the new array of + // physical devices. Everything else will have been copied over + // to the new array. + if (NULL != inst->phys_devs_term) { + for (uint32_t cur_pd = 0; cur_pd < inst->phys_dev_count_term; + cur_pd++) { + bool found = false; + for (uint32_t new_pd_idx = 0; + new_pd_idx < inst->total_gpu_count; + new_pd_idx++) { + if (inst->phys_devs_term[cur_pd] == + new_phys_devs[new_pd_idx]) { + found = true; + break; } } - loader_instance_heap_free(inst, inst->phys_devs_term); + if (!found) { + loader_instance_heap_free(inst, + inst->phys_devs_term[cur_pd]); + } } + loader_instance_heap_free(inst, inst->phys_devs_term); + } - // If we didn't load every device, the result is incomplete - if (copy_count < new_phys_dev_count) { - res = VK_INCOMPLETE; - } + // Swap out old and new devices list + inst->phys_dev_count_term = inst->total_gpu_count; + inst->phys_devs_term = new_phys_devs; + } - // Swap out old and new devices list - inst->phys_dev_count_term = new_phys_dev_count; - inst->phys_devs_term = new_phys_devs; + return res; +} - } else { - // Otherwise, we've encountered an error, so we should free the - // new buffers. - for (uint32_t j = 0; j < copy_count; j++) { - loader_instance_heap_free(inst, new_phys_devs[j]); - } - loader_instance_heap_free(inst, new_phys_devs); +VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices( + VkInstance instance, uint32_t *pPhysicalDeviceCount, + VkPhysicalDevice *pPhysicalDevices) { + struct loader_instance *inst = (struct loader_instance *)instance; + VkResult res = VK_SUCCESS; - // Set the copy count to 0 since something bad happened. - copy_count = 0; + // Only do the setup if we're re-querying the number of devices, or + // our count is currently 0. + if (NULL == pPhysicalDevices || 0 == inst->total_gpu_count) { + res = setupLoaderTermPhysDevs(inst); + if (VK_SUCCESS != res) { + goto out; + } + } + + uint32_t copy_count = inst->total_gpu_count; + if (NULL != pPhysicalDevices) { + if (copy_count > *pPhysicalDeviceCount) { + copy_count = *pPhysicalDeviceCount; + res = VK_INCOMPLETE; + } + + for (uint32_t i = 0; i < copy_count; i++) { + pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i]; } } *pPhysicalDeviceCount = copy_count; +out: + return res; } diff --git a/loader/loader.h b/loader/loader.h index aeceae6..45dc223 100644 --- a/loader/loader.h +++ b/loader/loader.h @@ -589,6 +589,9 @@ VkResult loader_validate_device_extensions( const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo); +VkResult setupLoaderTrampPhysDevs(VkInstance instance); +VkResult setupLoaderTermPhysDevs(struct loader_instance *inst); + /* instance layer chain termination entrypoint definitions */ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, diff --git a/loader/trampoline.c b/loader/trampoline.c index dbe0726..257ece7 100644 --- a/loader/trampoline.c +++ b/loader/trampoline.c @@ -221,6 +221,7 @@ vkEnumerateInstanceExtensionProperties(const char *pLayerName, } out: + loader_destroy_generic_list(NULL, (struct loader_generic_list *)&local_ext_list); loader_delete_layer_properties(NULL, &instance_layers); @@ -532,153 +533,58 @@ vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) { const VkLayerInstanceDispatchTable *disp; VkResult res = VK_SUCCESS; + uint32_t count, i; + struct loader_instance *inst; + disp = loader_get_instance_dispatch(instance); + loader_platform_thread_lock_mutex(&loader_lock); - uint32_t copy_count = 0; - struct loader_physical_device_tramp **new_phys_devs = NULL; - struct loader_instance *inst = loader_get_instance(instance); - VkPhysicalDevice *temp_pd_array = NULL; - uint32_t new_pd_count = 0; + inst = loader_get_instance(instance); if (NULL == inst) { res = VK_ERROR_INITIALIZATION_FAILED; goto out; } - disp = loader_get_instance_dispatch(instance); + if (pPhysicalDevices == NULL) { + // Call down. At the lower levels, this will setup the terminator + // structures in the loader. + res = disp->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, + pPhysicalDevices); + if (VK_SUCCESS != res) { + loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, + "vkEnumeratePhysicalDevices: Failed in dispatch call" + " used to determine number of available GPUs"); + } - // If they only want the count, just pass it in and return - res = disp->EnumeratePhysicalDevices(instance, ©_count, - NULL); - if (NULL == pPhysicalDevices) { + // Goto out, even on success since we don't need to fill in the rest. goto out; } - // Reset the copy count until we complete. - copy_count = 0; - - // If we're querying actual information, then we want to internally - // keep track of all GPUs. So, query them all, and we can trim the - // list down later. - new_pd_count = inst->total_gpu_count; - temp_pd_array = (VkPhysicalDevice *)loader_stack_alloc( - sizeof(VkPhysicalDevice) * new_pd_count); - if (NULL == temp_pd_array) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "vkEnumeratePhysicalDevices: Failed to allocate temporary " - "physical device array of size %d", - new_pd_count); - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - res = disp->EnumeratePhysicalDevices(instance, &new_pd_count, - temp_pd_array); - if (res != VK_SUCCESS && res != VK_INCOMPLETE) { + VkResult setup_res = setupLoaderTrampPhysDevs(instance); + if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) { + res = setup_res; goto out; } - // Determine how many items we need to create and return (via copying into - // the provided array). - copy_count = (new_pd_count < *pPhysicalDeviceCount) ? new_pd_count : - *pPhysicalDeviceCount; - - // Create a new array for the physical devices - new_phys_devs = (struct loader_physical_device_tramp **) - loader_instance_heap_alloc( - inst, new_pd_count * sizeof(struct loader_physical_device_tramp *), - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == new_phys_devs) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "vkEnumeratePhysicalDevices: Failed to allocate physical " - "device trampoline array of size %d", - new_pd_count); - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; + // Wrap the PhysDev object for loader usage, return wrapped objects + if (inst->total_gpu_count > *pPhysicalDeviceCount) { + loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0, + "vkEnumeratePhysicalDevices: Trimming device count down" + " by application request from %d to %d physical devices", + inst->total_gpu_count, *pPhysicalDeviceCount); + count = *pPhysicalDeviceCount; + res = VK_INCOMPLETE; + } else { + count = inst->total_gpu_count; + *pPhysicalDeviceCount = count; } - memset(new_phys_devs, 0, - new_pd_count * sizeof(struct loader_physical_device_tramp *)); - - // Copy or create everything to fill the new array of physical devices - for (uint32_t new_idx = 0; new_idx < new_pd_count; new_idx++) { - - // Check if this physical device is already in the old buffer - for (uint32_t old_idx = 0; - old_idx < inst->phys_dev_count_tramp; - old_idx++) { - if (temp_pd_array[new_idx] == - inst->phys_devs_tramp[old_idx]->phys_dev) { - new_phys_devs[new_idx] = inst->phys_devs_tramp[old_idx]; - break; - } - } - // If this physical device isn't in the old buffer, create it - if (NULL == new_phys_devs[new_idx]) { - new_phys_devs[new_idx] = (struct loader_physical_device_tramp *) - loader_instance_heap_alloc( - inst, sizeof(struct loader_physical_device_tramp), - VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE); - if (NULL == new_phys_devs[new_idx]) { - loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0, - "vkEnumeratePhysicalDevices: Failed to allocate " - "physical device trampoline object %d", - new_idx); - new_pd_count = new_idx; - res = VK_ERROR_OUT_OF_HOST_MEMORY; - goto out; - } - // Initialize the new physicalDevice object - loader_set_dispatch((void *)new_phys_devs[new_idx], inst->disp); - new_phys_devs[new_idx]->this_instance = inst; - new_phys_devs[new_idx]->phys_dev = temp_pd_array[new_idx]; - } - - if (new_idx < copy_count) { - // Copy wrapped object into Application provided array - pPhysicalDevices[new_idx] = - (VkPhysicalDevice)new_phys_devs[new_idx]; - } + for (i = 0; i < count; i++) { + pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_tramp[i]; } out: - if (NULL != pPhysicalDevices) { - // If there was no error, free the old buffer and assign the new one - if (res == VK_SUCCESS || res == VK_INCOMPLETE) { - // Free everything that didn't carry over to the new array of - // physical devices - if (NULL != inst->phys_devs_tramp) { - for (uint32_t i = 0; i < inst->phys_dev_count_tramp; i++) { - bool found = false; - for (uint32_t j = 0; j < new_pd_count; j++) { - if (inst->phys_devs_tramp[i] == new_phys_devs[j]) { - found = true; - break; - } - } - if (!found) { - loader_instance_heap_free(inst, - inst->phys_devs_tramp[i]); - } - } - loader_instance_heap_free(inst, inst->phys_devs_tramp); - } - - // Swap in the new physical device list - inst->phys_dev_count_tramp = new_pd_count; - inst->phys_devs_tramp = new_phys_devs; - } else { - for (uint32_t i = 0; i < new_pd_count; i++) { - loader_instance_heap_free(inst, new_phys_devs[i]); - } - loader_instance_heap_free(inst, new_phys_devs); - - // Set the copy count to 0 since something bad happened. - copy_count = 0; - } - } - - *pPhysicalDeviceCount = copy_count; - loader_platform_thread_unlock_mutex(&loader_lock); return res; } -- 2.7.4