Skip to content

Commit 1d2a2fd

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 4775d54 commit 1d2a2fd

File tree

12 files changed

+945
-56
lines changed

12 files changed

+945
-56
lines changed

loader/loader.c

Lines changed: 162 additions & 28 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
@@ -3801,18 +3803,26 @@ VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_t
38013803
goto out;
38023804
}
38033805

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

3814-
// Get a list of manifest files for ICDs
3815-
res = loader_get_data_files(inst, LOADER_DATA_FILE_MANIFEST_DRIVER, NULL, &manifest_files);
3824+
// Add any drivers provided by the loader settings file
3825+
res = loader_settings_get_additional_driver_files(inst, &manifest_files);
38163826
if (VK_SUCCESS != res) {
38173827
goto out;
38183828
}
@@ -5459,10 +5469,10 @@ VkResult loader_validate_device_extensions(struct loader_instance *this_instance
54595469
// All named terminator_<Vulkan API name>
54605470
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateInfo *pCreateInfo,
54615471
const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
5462-
struct loader_icd_term *icd_term;
5463-
VkExtensionProperties *prop;
5472+
struct loader_icd_term *icd_term = NULL;
5473+
VkExtensionProperties *prop = NULL;
54645474
char **filtered_extension_names = NULL;
5465-
VkInstanceCreateInfo icd_create_info;
5475+
VkInstanceCreateInfo icd_create_info = {0};
54665476
VkResult res = VK_SUCCESS;
54675477
bool one_icd_successful = false;
54685478

@@ -5650,7 +5660,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
56505660
}
56515661

56525662
// Create an instance, substituting the version to 1.0 if necessary
5653-
VkApplicationInfo icd_app_info;
5663+
VkApplicationInfo icd_app_info = {0};
56545664
const uint32_t api_variant = 0;
56555665
const uint32_t api_version_1_0 = VK_API_VERSION_1_0;
56565666
uint32_t icd_version_nopatch =
@@ -5667,6 +5677,25 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateInstance(const VkInstanceCreateI
56675677
icd_app_info.apiVersion = icd_version;
56685678
icd_create_info.pApplicationInfo = &icd_app_info;
56695679
}
5680+
5681+
// If the settings file has device_configurations, we need to raise the ApiVersion drivers use to 1.1 if the driver
5682+
// supports 1.1 or higher. This allows 1.0 apps to use the device_configurations without the app having to set its own
5683+
// ApiVersion to 1.1 on its own.
5684+
if (ptr_instance->settings.settings_active && ptr_instance->settings.device_configuration_count > 0 &&
5685+
icd_version >= VK_API_VERSION_1_1 && requested_version < VK_API_VERSION_1_1) {
5686+
if (NULL != pCreateInfo->pApplicationInfo) {
5687+
memcpy(&icd_app_info, pCreateInfo->pApplicationInfo, sizeof(VkApplicationInfo));
5688+
}
5689+
icd_app_info.apiVersion = VK_API_VERSION_1_1;
5690+
icd_create_info.pApplicationInfo = &icd_app_info;
5691+
5692+
loader_log(
5693+
ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
5694+
"terminator_CreateInstance: Raising the VkApplicationInfo::apiVersion from 1.0 to 1.1 on driver \"%s\" so that "
5695+
"the loader settings file is able to use this driver in the device_configuration selection logic.",
5696+
icd_term->scanned_icd->lib_name);
5697+
}
5698+
56705699
icd_result =
56715700
ptr_instance->icd_tramp_list.scanned_list[i].CreateInstance(&icd_create_info, pAllocator, &(icd_term->instance));
56725701
if (VK_ERROR_OUT_OF_HOST_MEMORY == icd_result) {
@@ -6780,28 +6809,133 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDevices(VkInstance in
67806809
goto out;
67816810
}
67826811

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

6793-
for (uint32_t i = 0; i < copy_count; i++) {
6794-
pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
6834+
for (uint32_t i = 0; i < copy_count; i++) {
6835+
pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_term[i];
6836+
}
67956837
}
6796-
}
67976838

6798-
*pPhysicalDeviceCount = copy_count;
6839+
*pPhysicalDeviceCount = copy_count;
6840+
}
67996841

68006842
out:
68016843

68026844
return res;
68036845
}
68046846

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