Skip to content

Commit a857f29

Browse files
Add device and drivers fields to settings file
The loader settings file now can specify additional drivers to include, whether to use those drivers exclusively, and filter/sort the VkPhysicalDevices using the settings file provided list of deviceUUID's. This lets the settings file control which drivers and/or devices are reported by the loader, giving greater control over the runtime behavior of the loader. device_configurations is an array of JSON objects which contain two fields each, deviceUUID and deviceName. deviceUUID is an array of 16 uint8_t's (expressed simply as numbers) which takes the value of the VkPhysicalDeviceVulkan11Properties::deviceUUID struct member. deviceName is a string taken from VkPhysicalDeviceProperties::deviceName. Only deviceUUID is used to filter and sort VkPhysicalDevices, deviceName is for convenience and ease of understanding the JSON loader settings file. additional_drivers is an array of JSON object which contain just one field, path, which is a path to the Manifest ICD JSON file for a driver. additional_drivers_use_exclusively is a boolean field indicating whether the loader should: if false (default if unspecified) - look for drivers in the normal locations and append the additional_drivers to the back of the driver list. if true - only use drivers in the additional_drivers, ignoring all other driver search locations.
1 parent 01526ab commit a857f29

12 files changed

Lines changed: 940 additions & 52 deletions

loader/loader.c

Lines changed: 152 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -3257,12 +3257,14 @@ VkResult read_data_files_in_search_paths(const struct loader_instance *inst, enu
32573257

32583258
switch (manifest_type) {
32593259
case LOADER_DATA_FILE_MANIFEST_DRIVER:
3260-
override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst);
3261-
if (NULL == override_env) {
3262-
// Not there, so fall back to the old name
3263-
override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst);
3260+
if (loader_settings_should_use_driver_environment_variables(inst)) {
3261+
override_env = loader_secure_getenv(VK_DRIVER_FILES_ENV_VAR, inst);
3262+
if (NULL == override_env) {
3263+
// Not there, so fall back to the old name
3264+
override_env = loader_secure_getenv(VK_ICD_FILENAMES_ENV_VAR, inst);
3265+
}
3266+
additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst);
32643267
}
3265-
additional_env = loader_secure_getenv(VK_ADDITIONAL_DRIVER_FILES_ENV_VAR, inst);
32663268
#if COMMON_UNIX_PLATFORMS
32673269
relative_location = VK_DRIVERS_INFO_RELATIVE_DIR;
32683270
#endif
@@ -3802,18 +3804,26 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
38023804
goto out;
38033805
}
38043806

3805-
// Parse the filter environment variables to determine if we have any special behavior
3806-
res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter);
3807-
if (VK_SUCCESS != res) {
3808-
goto out;
3807+
if (loader_settings_should_use_driver_environment_variables(inst)) {
3808+
// Parse the filter environment variables to determine if we have any special behavior
3809+
res = parse_generic_filter_environment_var(inst, VK_DRIVERS_SELECT_ENV_VAR, &select_filter);
3810+
if (VK_SUCCESS != res) {
3811+
goto out;
3812+
}
3813+
res = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter);
3814+
if (VK_SUCCESS != res) {
3815+
goto out;
3816+
}
38093817
}
3810-
res = parse_generic_filter_environment_var(inst, VK_DRIVERS_DISABLE_ENV_VAR, &disable_filter);
3818+
3819+
// Get a list of manifest files for ICDs
3820+
res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
38113821
if (VK_SUCCESS != res) {
38123822
goto out;
38133823
}
38143824

3815-
// Get a list of manifest files for ICDs
3816-
res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
3825+
// Add any drivers provided by the loader settings file
3826+
res = loader_settings_get_additional_driver_files(inst, &manifest_files);
38173827
if (VK_SUCCESS != res) {
38183828
goto out;
38193829
}
@@ -5659,6 +5669,19 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
56595669
uint32_t requested_version = (pCreateInfo == NULL || pCreateInfo->pApplicationInfo == NULL)
56605670
? api_version_1_0
56615671
: pCreateInfo->pApplicationInfo->apiVersion;
5672+
// If the settings file has device_configurations, we need to raise the ApiVersion drivers use to 1.1 if the driver
5673+
// supports 1.1 or higher. This allows 1.0 apps to use the device_configurations without the app having to set its own
5674+
// ApiVersion to 1.1 on its own.
5675+
if (ptr_instance->settings.settings_active && ptr_instance->settings.device_configuration_count > 0 &&
5676+
icd_version >= VK_API_VERSION_1_1 && requested_version < VK_API_VERSION_1_1) {
5677+
requested_version = VK_API_VERSION_1_1;
5678+
loader_log(
5679+
ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
5680+
"terminator_CreateInstance: Raising the VkApplicationInfo::apiVersion from 1.0 to 1.1 on driver \"%s\" so that "
5681+
"the loader settings file is able to use this driver in the device_configuration selection logic.",
5682+
icd_term->scanned_icd->lib_name);
5683+
}
5684+
56625685
if ((requested_version != 0) && (icd_version_nopatch == api_version_1_0)) {
56635686
if (icd_create_info.pApplicationInfo == NULL) {
56645687
memset(&icd_app_info, 0, sizeof(icd_app_info));
@@ -6781,28 +6804,133 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance in
67816804
goto out;
67826805
}
67836806

6784-
uint32_t copy_count = inst->phys_dev_count_term;
6785-
if (NULL != pPhysicalDevices) {
6786-
if (copy_count > *pPhysicalDeviceCount) {
6787-
copy_count = *pPhysicalDeviceCount;
6788-
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
6789-
"terminator_EnumeratePhysicalDevices : Trimming device count from %d to %d.", inst->phys_dev_count_term,
6790-
copy_count);
6791-
res = VK_INCOMPLETE;
6807+
if (inst->settings.settings_active && inst->settings.device_configuration_count > 0) {
6808+
// Use settings file device_configurations if present
6809+
if (NULL == pPhysicalDevices) {
6810+
// take the minimum of the settings configurations count and number of terminators
6811+
*pPhysicalDeviceCount = (inst->settings.device_configuration_count < inst->phys_dev_count_term)
6812+
? inst->settings.device_configuration_count
6813+
: inst->phys_dev_count_term;
6814+
} else {
6815+
res = loader_apply_settings_device_configurations(inst, pPhysicalDeviceCount, pPhysicalDevices);
67926816
}
6817+
} else {
6818+
// Otherwise just copy the physical devices up normally and pass it up the chain
6819+
uint32_t copy_count = inst->phys_dev_count_term;
6820+
if (NULL != pPhysicalDevices) {
6821+
if (copy_count > *pPhysicalDeviceCount) {
6822+
copy_count = *pPhysicalDeviceCount;
6823+
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
6824+
"terminator_EnumeratePhysicalDevices : Trimming device count from %d to %d.", inst->phys_dev_count_term,
6825+
copy_count);
6826+
res = VK_INCOMPLETE;
6827+
}
67936828

6794-
for (uint32_t i = 0; i < copy_count; i++) {
6795-
pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
6829+
for (uint32_t i = 0; i < copy_count; i++) {
6830+
pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
6831+
}
67966832
}
6797-
}
67986833

6799-
*pPhysicalDeviceCount = copy_count;
6834+
*pPhysicalDeviceCount = copy_count;
6835+
}
68006836

68016837
out:
68026838

68036839
return res;
68046840
}
68056841

6842+
// Apply the device_configurations in the settings file to the output VkPhysicalDeviceList.
6843+
// That means looking up each VkPhysicalDevice's deviceUUID, filtering using that, and putting them in the order of
6844+
// device_configurations in the settings file.
6845+
VkResult loader_apply_settings_device_configurations(struct loader_instance *inst, uint32_t *pPhysicalDeviceCount,
6846+
VkPhysicalDevice *pPhysicalDevices) {
6847+
bool *pd_supports_11 = loader_stack_alloc(inst->phys_dev_count_term * sizeof(bool));
6848+
if (NULL == pd_supports_11) {
6849+
return VK_ERROR_OUT_OF_HOST_MEMORY;
6850+
}
6851+
memset(pd_supports_11, 0, inst->phys_dev_count_term * sizeof(bool));
6852+
6853+
VkPhysicalDeviceProperties *pd_props = loader_stack_alloc(inst->phys_dev_count_term * sizeof(VkPhysicalDeviceProperties));
6854+
if (NULL == pd_props) {
6855+
return VK_ERROR_OUT_OF_HOST_MEMORY;
6856+
}
6857+
memset(pd_props, 0, inst->phys_dev_count_term * sizeof(VkPhysicalDeviceProperties));
6858+
6859+
VkPhysicalDeviceVulkan11Properties *pd_vulkan_11_props =
6860+
loader_stack_alloc(inst->phys_dev_count_term * sizeof(VkPhysicalDeviceVulkan11Properties));
6861+
if (NULL == pd_vulkan_11_props) {
6862+
return VK_ERROR_OUT_OF_HOST_MEMORY;
6863+
}
6864+
memset(pd_vulkan_11_props, 0, inst->phys_dev_count_term * sizeof(VkPhysicalDeviceVulkan11Properties));
6865+
6866+
for (uint32_t i = 0; i < inst->phys_dev_count_term; i++) {
6867+
pd_vulkan_11_props[i].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_1_PROPERTIES;
6868+
6869+
inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties(inst->phys_devs_term[i]->phys_dev,
6870+
&pd_props[i]);
6871+
if (pd_props[i].apiVersion >= VK_API_VERSION_1_1) {
6872+
pd_supports_11[i] = true;
6873+
VkPhysicalDeviceProperties2 props2 = {0};
6874+
props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
6875+
props2.pNext = (void *)&pd_vulkan_11_props[i];
6876+
if (inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties2) {
6877+
inst->phys_devs_term[i]->this_icd_term->dispatch.GetPhysicalDeviceProperties2(inst->phys_devs_term[i]->phys_dev,
6878+
&props2);
6879+
}
6880+
}
6881+
}
6882+
6883+
// Loop over the setting's device configurations, find each VkPhysicalDevice which matches the deviceUUID given, add to the
6884+
// pPhysicalDevices output list.
6885+
uint32_t written_output_index = 0;
6886+
6887+
for (uint32_t i = 0; i < inst->settings.device_configuration_count; i++) {
6888+
uint8_t *current_deviceUUID = inst->settings.device_configurations[i].deviceUUID;
6889+
bool configuration_found = false;
6890+
for (uint32_t j = 0; j < inst->phys_dev_count_term; j++) {
6891+
// Don't compare deviceUUID's if they have nothing, since we require deviceUUID's to effectively sort them.
6892+
if (!pd_supports_11[j]) {
6893+
continue;
6894+
}
6895+
if (memcmp(current_deviceUUID, pd_vulkan_11_props[j].deviceUUID, sizeof(uint8_t) * VK_UUID_SIZE) == 0) {
6896+
configuration_found = true;
6897+
// Catch when there are more device_configurations than space available in the output
6898+
if (written_output_index >= *pPhysicalDeviceCount) {
6899+
*pPhysicalDeviceCount = written_output_index; // write out how many were written
6900+
return VK_INCOMPLETE;
6901+
}
6902+
pPhysicalDevices[written_output_index++] = (VkPhysicalDevice)inst->phys_devs_term[j];
6903+
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Insert VkPhysicalDevice \"%s\" to the pPhysicalDevices list",
6904+
pd_props[j].deviceName);
6905+
break;
6906+
}
6907+
}
6908+
if (!configuration_found) {
6909+
uint8_t *id = current_deviceUUID;
6910+
// Log that this configuration was missing.
6911+
if (inst->settings.device_configurations[i].deviceName[0] != '\0') {
6912+
loader_log(
6913+
inst, VULKAN_LOADER_WARN_BIT, 0,
6914+
"loader_apply_settings_device_configurations: settings file contained device_configuration which does not "
6915+
"appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceName: \"%s\" and deviceUUID: "
6916+
"[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]",
6917+
inst->settings.device_configurations[i].deviceName, id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7],
6918+
id[8], id[9], id[10], id[11], id[12], id[13], id[14], id[15]);
6919+
} else {
6920+
loader_log(
6921+
inst, VULKAN_LOADER_WARN_BIT, 0,
6922+
"loader_apply_settings_device_configurations: settings file contained device_configuration which does not "
6923+
"appear in the enumerated VkPhysicalDevices. Missing VkPhysicalDevice with deviceUUID: "
6924+
"[%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d]",
6925+
id[0], id[1], id[2], id[3], id[4], id[5], id[6], id[7], id[8], id[9], id[10], id[11], id[12], id[13], id[14],
6926+
id[15]);
6927+
}
6928+
}
6929+
}
6930+
*pPhysicalDeviceCount = written_output_index; // update with how many were written
6931+
return VK_SUCCESS;
6932+
}
6933+
68066934
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
68076935
const char *pLayerName, uint32_t *pPropertyCount,
68086936
VkExtensionProperties *pProperties) {

loader/loader.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,9 @@ VkResult setup_loader_tramp_phys_dev_groups(struct loader_instance *inst, uint32
221221
VkPhysicalDeviceGroupProperties *groups);
222222
void unload_drivers_without_physical_devices(struct loader_instance *inst);
223223

224+
VkResult loader_apply_settings_device_configurations(struct loader_instance *inst, uint32_t *pPhysicalDeviceCount,
225+
VkPhysicalDevice *pPhysicalDevices);
226+
224227
VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
225228
char *loader_get_next_path(char *path);
226229
VkResult add_if_manifest_file(const struct loader_instance *inst, const char *file_name, struct loader_string_list *out_files);

0 commit comments

Comments
 (0)