Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
130 changes: 130 additions & 0 deletions loader/loader.c
Original file line number Diff line number Diff line change
Expand Up @@ -7986,3 +7986,133 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumeratePhysicalDeviceGroups(
}
return res;
}

VkResult get_device_driver_id(VkPhysicalDevice physicalDevice, VkDriverId *driverId) {
VkPhysicalDeviceDriverProperties physical_device_driver_props = {0};
physical_device_driver_props.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES;

VkPhysicalDeviceProperties2 props2 = {0};
props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
props2.pNext = &physical_device_driver_props;

struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
const struct loader_instance *inst = icd_term->this_instance;

assert(inst != NULL);

// Get the function pointer to use to call into the ICD. This could be the core or KHR version
PFN_vkGetPhysicalDeviceProperties2 fpGetPhysicalDeviceProperties2 = NULL;
if (loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version)) {
fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2;
}
if (fpGetPhysicalDeviceProperties2 == NULL && inst->enabled_extensions.khr_get_physical_device_properties2) {
fpGetPhysicalDeviceProperties2 = icd_term->dispatch.GetPhysicalDeviceProperties2KHR;
}

if (fpGetPhysicalDeviceProperties2 == NULL) {
*driverId = 0;
return VK_ERROR_UNKNOWN;
}

fpGetPhysicalDeviceProperties2(phys_dev_term->phys_dev, &props2);

*driverId = physical_device_driver_props.driverID;
return VK_SUCCESS;
}

VkResult loader_filter_enumerated_physical_device(const struct loader_instance *inst,
const struct loader_envvar_id_filter *device_id_filter,
const struct loader_envvar_id_filter *vendor_id_filter,
const struct loader_envvar_id_filter *driver_id_filter,
const uint32_t in_PhysicalDeviceCount,
const VkPhysicalDevice *in_pPhysicalDevices, uint32_t *out_pPhysicalDeviceCount,
VkPhysicalDevice *out_pPhysicalDevices) {
uint32_t filtered_physical_device_count = 0;
for (uint32_t i = 0; i < in_PhysicalDeviceCount; i++) {
VkPhysicalDeviceProperties dev_props = {0};
inst->disp->layer_inst_disp.GetPhysicalDeviceProperties(in_pPhysicalDevices[i], &dev_props);

if ((0 != device_id_filter->count) && !check_id_matches_filter_environment_var(dev_props.deviceID, device_id_filter)) {
continue;
}

if ((0 != vendor_id_filter->count) && !check_id_matches_filter_environment_var(dev_props.vendorID, vendor_id_filter)) {
continue;
}

if (0 != driver_id_filter->count) {
VkDriverId driver_id;
VkResult res = get_device_driver_id(in_pPhysicalDevices[i], &driver_id);

if ((res != VK_SUCCESS) || !check_id_matches_filter_environment_var(driver_id, driver_id_filter)) {
continue;
}
}

if ((NULL != out_pPhysicalDevices) && (filtered_physical_device_count < *out_pPhysicalDeviceCount)) {
out_pPhysicalDevices[filtered_physical_device_count] = in_pPhysicalDevices[i];
}
filtered_physical_device_count++;
}

if ((NULL == out_pPhysicalDevices) || (filtered_physical_device_count < *out_pPhysicalDeviceCount)) {
*out_pPhysicalDeviceCount = filtered_physical_device_count;
}

return (*out_pPhysicalDeviceCount < filtered_physical_device_count) ? VK_INCOMPLETE : VK_SUCCESS;
}

VkResult loader_filter_enumerated_physical_device_groups(
const struct loader_instance *inst, const struct loader_envvar_id_filter *device_id_filter,
const struct loader_envvar_id_filter *vendor_id_filter, const struct loader_envvar_id_filter *driver_id_filter,
const uint32_t in_PhysicalDeviceGroupCount, const VkPhysicalDeviceGroupProperties *in_pPhysicalDeviceGroupProperties,
uint32_t *out_PhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *out_pPhysicalDeviceGroupProperties) {
uint32_t filtered_physical_device_group_count = 0;
for (uint32_t i = 0; i < in_PhysicalDeviceGroupCount; i++) {
const VkPhysicalDeviceGroupProperties *device_group = &in_pPhysicalDeviceGroupProperties[i];

bool skip_group = false;
for (uint32_t j = 0; j < device_group->physicalDeviceCount; j++) {
VkPhysicalDeviceProperties dev_props = {0};
inst->disp->layer_inst_disp.GetPhysicalDeviceProperties(device_group->physicalDevices[j], &dev_props);

if ((0 != device_id_filter->count) && !check_id_matches_filter_environment_var(dev_props.deviceID, device_id_filter)) {
skip_group = true;
break;
}

if ((0 != vendor_id_filter->count) && !check_id_matches_filter_environment_var(dev_props.vendorID, vendor_id_filter)) {
skip_group = true;
break;
}

if (0 != driver_id_filter->count) {
VkDriverId driver_id;
VkResult res = get_device_driver_id(device_group->physicalDevices[j], &driver_id);

if ((res != VK_SUCCESS) || !check_id_matches_filter_environment_var(driver_id, driver_id_filter)) {
skip_group = true;
break;
}
}
}

if (skip_group) {
continue;
}

if ((NULL != out_pPhysicalDeviceGroupProperties) &&
(filtered_physical_device_group_count < *out_PhysicalDeviceGroupCount)) {
out_pPhysicalDeviceGroupProperties[filtered_physical_device_group_count] = *device_group;
}

filtered_physical_device_group_count++;
}

if ((NULL == out_pPhysicalDeviceGroupProperties) || (filtered_physical_device_group_count < *out_PhysicalDeviceGroupCount)) {
*out_PhysicalDeviceGroupCount = filtered_physical_device_group_count;
}

return (*out_PhysicalDeviceGroupCount < filtered_physical_device_group_count) ? VK_INCOMPLETE : VK_SUCCESS;
}
14 changes: 14 additions & 0 deletions loader/loader.h
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,20 @@ loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32
// Helper macros for determining if a version is valid or not
bool loader_check_version_meets_required(loader_api_version required, loader_api_version version);

VkResult loader_filter_enumerated_physical_device(const struct loader_instance *inst,
const struct loader_envvar_id_filter *device_id_filter,
const struct loader_envvar_id_filter *vendor_id_filter,
const struct loader_envvar_id_filter *driver_id_filter,
const uint32_t in_PhysicalDeviceCount,
const VkPhysicalDevice *in_pPhysicalDevices, uint32_t *out_pPhysicalDeviceCount,
VkPhysicalDevice *out_pPhysicalDevices);

VkResult loader_filter_enumerated_physical_device_groups(
const struct loader_instance *inst, const struct loader_envvar_id_filter *device_id_filter,
const struct loader_envvar_id_filter *vendor_id_filter, const struct loader_envvar_id_filter *driver_id_filter,
const uint32_t in_PhysicalDeviceGroupCount, const VkPhysicalDeviceGroupProperties *in_pPhysicalDeviceGroupProperties,
uint32_t *out_PhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *out_pPhysicalDeviceGroupProperties);

// Convenience macros for common versions
#if !defined(LOADER_VERSION_1_0_0)
#define LOADER_VERSION_1_0_0 loader_combine_version(1, 0, 0)
Expand Down
10 changes: 10 additions & 0 deletions loader/loader_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -521,3 +521,13 @@ struct loader_envvar_all_filters {
struct loader_envvar_disable_layers_filter disable_filter;
struct loader_envvar_filter allow_filter;
};

struct loader_envvar_id_filter_value {
uint32_t begin;
uint32_t end;
};

struct loader_envvar_id_filter {
uint32_t count;
struct loader_envvar_id_filter_value filters[MAX_ADDITIONAL_FILTERS];
};
53 changes: 53 additions & 0 deletions loader/loader_environment.c
Original file line number Diff line number Diff line change
Expand Up @@ -566,3 +566,56 @@ VkResult loader_add_environment_layers(struct loader_instance *inst, const enum

return res;
}

void parse_id_filter_enviroment_var(const struct loader_instance *inst, const char *env_var_name,
struct loader_envvar_id_filter *filter_struct) {
memset(filter_struct, 0, sizeof(struct loader_envvar_id_filter));
char *parsing_string = NULL;
char *env_var_value = loader_secure_getenv(env_var_name, inst);
if (NULL == env_var_value) {
return;
}
const size_t env_var_len = strlen(env_var_value);
if (env_var_len == 0) {
goto out;
}
// Allocate a separate string since scan_for_next_comma modifies the original string
parsing_string = loader_stack_alloc(env_var_len + 1);
for (uint32_t iii = 0; iii < env_var_len; ++iii) {
parsing_string[iii] = (char)tolower(env_var_value[iii]);
}
parsing_string[env_var_len] = '\0';

filter_struct->count = 0;
char *context = NULL;
char *token = thread_safe_strtok(parsing_string, ",", &context);
while (NULL != token) {
struct loader_envvar_id_filter_value *filter_value = &filter_struct->filters[filter_struct->count];

char *pEnd;
filter_value->begin = (uint32_t)strtoul(token, &pEnd, 0);

if (*pEnd != '\0') {
pEnd++;
filter_value->end = (uint32_t)strtoul(pEnd, NULL, 0);
} else {
filter_value->end = filter_value->begin;
}

filter_struct->count++;
token = thread_safe_strtok(NULL, ",", &context);
}

out:

loader_free_getenv(env_var_value, inst);
}

bool check_id_matches_filter_environment_var(const uint32_t id, const struct loader_envvar_id_filter *filter_struct) {
for (uint32_t i = 0; i < filter_struct->count; i++) {
if ((filter_struct->filters[i].begin <= id) && (id <= filter_struct->filters[i].end)) {
return true;
}
}
return false;
}
4 changes: 4 additions & 0 deletions loader/loader_environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,7 @@ VkResult loader_add_environment_layers(struct loader_instance *inst, const enum
struct loader_pointer_layer_list *target_list,
struct loader_pointer_layer_list *expanded_target_list,
const struct loader_layer_list *source_list);

void parse_id_filter_enviroment_var(const struct loader_instance *inst, const char *env_var_name,
struct loader_envvar_id_filter *filter_struct);
bool check_id_matches_filter_environment_var(const uint32_t id, const struct loader_envvar_id_filter *filter_struct);
64 changes: 61 additions & 3 deletions loader/trampoline.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "loader_environment.h"
#include "log.h"
#include "settings.h"
#include "stack_allocation.h"
#include "vk_loader_extensions.h"
#include "vk_loader_platform.h"
#include "wsi.h"
Expand Down Expand Up @@ -852,8 +853,34 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstan
goto out;
}

struct loader_envvar_id_filter device_id_filter;
struct loader_envvar_id_filter vendor_id_filter;
struct loader_envvar_id_filter driver_id_filter;

parse_id_filter_enviroment_var(inst, VK_DEVICE_ID_FILTER_ENV_VAR, &device_id_filter);
parse_id_filter_enviroment_var(inst, VK_VENDOR_ID_FILTER_ENV_VAR, &vendor_id_filter);
parse_id_filter_enviroment_var(inst, VK_DRIVER_ID_FILTER_ENV_VAR, &driver_id_filter);

// Call down the chain to get the physical device info
res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(inst->instance, pPhysicalDeviceCount, pPhysicalDevices);
if ((0 == device_id_filter.count) && (0 == vendor_id_filter.count) && (0 == driver_id_filter.count)) {
res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(inst->instance, pPhysicalDeviceCount, pPhysicalDevices);
} else {
uint32_t physical_device_count = 0;
res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(inst->instance, &physical_device_count, NULL);
if (res != VK_SUCCESS) {
goto out;
}

VkPhysicalDevice *physical_devices = loader_stack_alloc(physical_device_count * sizeof(VkPhysicalDevice));
res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(inst->instance, &physical_device_count, physical_devices);
if (res != VK_SUCCESS) {
goto out;
}

res = loader_filter_enumerated_physical_device(inst, &device_id_filter, &vendor_id_filter, &driver_id_filter,
physical_device_count, physical_devices, pPhysicalDeviceCount,
pPhysicalDevices);
}

if (NULL != pPhysicalDevices && (VK_SUCCESS == res || VK_INCOMPLETE == res)) {
// Wrap the PhysDev object for loader usage, return wrapped objects
Expand Down Expand Up @@ -2586,9 +2613,40 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
goto out;
}

struct loader_envvar_id_filter device_id_filter;
struct loader_envvar_id_filter vendor_id_filter;
struct loader_envvar_id_filter driver_id_filter;

parse_id_filter_enviroment_var(inst, VK_DEVICE_ID_FILTER_ENV_VAR, &device_id_filter);
parse_id_filter_enviroment_var(inst, VK_VENDOR_ID_FILTER_ENV_VAR, &vendor_id_filter);
parse_id_filter_enviroment_var(inst, VK_DRIVER_ID_FILTER_ENV_VAR, &driver_id_filter);

// Call down the chain to get the physical device group info.
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups(inst->instance, pPhysicalDeviceGroupCount,
pPhysicalDeviceGroupProperties);
if ((0 == device_id_filter.count) && (0 == vendor_id_filter.count) && (0 == driver_id_filter.count)) {
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups(inst->instance, pPhysicalDeviceGroupCount,
pPhysicalDeviceGroupProperties);
} else {
uint32_t physical_device_group_count = 0;
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups(inst->instance, &physical_device_group_count, NULL);
if (res != VK_SUCCESS) {
goto out;
}

VkPhysicalDeviceGroupProperties *physical_device_group_properties =
loader_stack_alloc(physical_device_group_count * sizeof(VkPhysicalDeviceGroupProperties));
memset(physical_device_group_properties, 0, physical_device_group_count * sizeof(VkPhysicalDeviceGroupProperties));

res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups(inst->instance, &physical_device_group_count,
physical_device_group_properties);
if (res != VK_SUCCESS) {
goto out;
}

res = loader_filter_enumerated_physical_device_groups(inst, &device_id_filter, &vendor_id_filter, &driver_id_filter,
physical_device_group_count, physical_device_group_properties,
pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
}

if (NULL != pPhysicalDeviceGroupProperties && (VK_SUCCESS == res || VK_INCOMPLETE == res)) {
// Wrap the PhysDev object for loader usage, return wrapped objects
VkResult update_res = setup_loader_tramp_phys_dev_groups(inst, *pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
Expand Down
4 changes: 4 additions & 0 deletions loader/vk_loader_platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,10 @@
#define VK_IMPLICIT_LAYER_PATH_ENV_VAR "VK_IMPLICIT_LAYER_PATH"
#define VK_ADDITIONAL_IMPLICIT_LAYER_PATH_ENV_VAR "VK_ADD_IMPLICIT_LAYER_PATH"

#define VK_DEVICE_ID_FILTER_ENV_VAR "VK_LOADER_DEVICE_ID_FILTER"
#define VK_VENDOR_ID_FILTER_ENV_VAR "VK_LOADER_VENDOR_ID_FILTER"
#define VK_DRIVER_ID_FILTER_ENV_VAR "VK_LOADER_DRIVER_ID_FILTER"

// Override layer information
#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"

Expand Down
4 changes: 4 additions & 0 deletions tests/framework/icd/test_icd.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1232,6 +1232,10 @@ VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties2(VkPhysicalDevice
auto* vulkan_11_props = reinterpret_cast<VkPhysicalDeviceVulkan11Properties*>(pNext);
memcpy(vulkan_11_props->deviceUUID, phys_dev.deviceUUID.data(), VK_UUID_SIZE);
}
if (pNext->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES) {
auto* device_driver_props = reinterpret_cast<VkPhysicalDeviceDriverProperties*>(pNext);
*device_driver_props = phys_dev.driver_properties;
}
pNext = reinterpret_cast<VkBaseInStructure*>(const_cast<VkBaseInStructure*>(pNext->pNext));
}
}
Expand Down
1 change: 1 addition & 0 deletions tests/framework/icd/test_icd.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ struct PhysicalDevice {
BUILDER_VALUE(VkPhysicalDeviceProperties, properties)
BUILDER_VALUE(VkPhysicalDeviceFeatures, features)
BUILDER_VALUE(VkPhysicalDeviceMemoryProperties, memory_properties)
BUILDER_VALUE(VkPhysicalDeviceDriverProperties, driver_properties)
BUILDER_VALUE(VkImageFormatProperties, image_format_properties)
BUILDER_VALUE(VkExternalMemoryProperties, external_memory_properties)
BUILDER_VALUE(VkExternalSemaphoreProperties, external_semaphore_properties)
Expand Down
3 changes: 3 additions & 0 deletions tests/framework/test_environment.h
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,9 @@ struct FrameworkEnvironment {
EnvVarWrapper add_env_var_vk_layer_paths{"VK_ADD_LAYER_PATH"};
EnvVarWrapper env_var_vk_implicit_layer_paths{"VK_IMPLICIT_LAYER_PATH"};
EnvVarWrapper add_env_var_vk_implicit_layer_paths{"VK_ADD_IMPLICIT_LAYER_PATH"};
EnvVarWrapper env_var_vk_loader_device_id_filter{"VK_LOADER_DEVICE_ID_FILTER"};
EnvVarWrapper env_var_vk_loader_vendor_id_filter{"VK_LOADER_VENDOR_ID_FILTER"};
EnvVarWrapper env_var_vk_loader_driver_id_filter{"VK_LOADER_DRIVER_ID_FILTER"};

#if TESTING_COMMON_UNIX_PLATFORMS
EnvVarWrapper env_var_home{"HOME", "/home/fake_home"};
Expand Down
Loading
Loading