summaryrefslogtreecommitdiff
path: root/loader
diff options
context:
space:
mode:
authorMark Young <marky@lunarg.com>2017-01-12 12:27:19 -0700
committerMark Young <marky@lunarg.com>2017-01-12 15:02:12 -0700
commitd4dc58b9ae008d6fad2eb24602b61a75b3186423 (patch)
tree2608bf86ce26eb2de53830e09f75f8811e6d047f /loader
parentbcb80d06bbdc0910792549c7399d4ac43a94ea09 (diff)
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
Diffstat (limited to 'loader')
-rw-r--r--loader/loader.c461
-rw-r--r--loader/loader.h3
-rw-r--r--loader/trampoline.c160
3 files changed, 326 insertions, 298 deletions
diff --git a/loader/loader.c b/loader/loader.c
index 4179106c..16bfcedb 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 aeceae63..45dc223b 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 dbe0726b..257ece7b 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, &copy_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;
}