Loader single EnumPhysDev call through layers

The loader trampoline previously would query all devices every time
vkEnumeratePhysicalDevices was called.
To do this, it would make two calls every time:
  - First, it would ignore the passed in user values
  - Second, it would query the total number of available devices.
  - Third, it would query the values for every available device

This resulted in layers reporting 2 vkEnumeratePhysicalDevices call for
every 1 the application made which could get very polluted in output.
It didn't break any functionality, just made things messy.

This change removes that behavior and adds a bunch of test cases to verify
nothing broke in the move.
This commit is contained in:
Mark Young
2021-12-02 16:55:13 -07:00
parent 656dfc1ae0
commit d4701211de
17 changed files with 2966 additions and 885 deletions
+510 -407
View File
File diff suppressed because it is too large Load Diff
+5 -5
View File
@@ -1,8 +1,8 @@
/*
*
* Copyright (c) 2014-2021 The Khronos Group Inc.
* Copyright (c) 2014-2021 Valve Corporation
* Copyright (c) 2014-2021 LunarG, Inc.
* Copyright (c) 2014-2022 The Khronos Group Inc.
* Copyright (c) 2014-2022 Valve Corporation
* Copyright (c) 2014-2022 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@@ -164,8 +164,8 @@ VkResult loader_validate_device_extensions(struct loader_instance *this_instance
const struct loader_layer_list *activated_device_layers,
const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo);
VkResult setup_loader_tramp_phys_devs(struct loader_instance *inst);
VkResult setup_loader_term_phys_devs(struct loader_instance *inst);
VkResult setup_loader_tramp_phys_devs(struct loader_instance *inst, uint32_t phys_dev_count, VkPhysicalDevice *phys_devs);
VkResult setup_loader_tramp_phys_dev_groups(struct loader_instance *inst, uint32_t group_count, VkPhysicalDeviceGroupProperties *groups);
VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
char *loader_get_next_path(char *path);
-2
View File
@@ -271,8 +271,6 @@ struct loader_instance {
// device stored internal to the public structures.
uint32_t phys_dev_group_count_term;
struct VkPhysicalDeviceGroupProperties **phys_dev_groups_term;
uint32_t phys_dev_group_count_tramp;
struct VkPhysicalDeviceGroupProperties **phys_dev_groups_tramp;
struct loader_instance *next;
+9 -2
View File
@@ -219,7 +219,8 @@ static void linux_env_var_default_device(struct loader_instance *inst, uint32_t
for (int32_t i = 0; i < (int32_t)device_count; ++i) {
if (sorted_device_info[i].vendor_id == vendor_id && sorted_device_info[i].device_id == device_id) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
"linux_env_var_default_device: Found default at index %u \'%s\'", i, sorted_device_info[i].device_name);
"linux_env_var_default_device: Found default at index %u \'%s\'", i,
sorted_device_info[i].device_name);
sorted_device_info[i].default_device = true;
break;
}
@@ -424,6 +425,11 @@ VkResult linux_read_sorted_physical_device_groups(struct loader_instance *inst,
// Sort GPUs in each group
qsort(sorted_group_term[group].internal_device_info, sorted_group_term[group].group_props.physicalDeviceCount,
sizeof(struct LinuxSortedDeviceInfo), compare_devices);
// Match the externally used physical device list with the sorted physical device list for this group.
for (uint32_t dev = 0; dev < sorted_group_term[group].group_props.physicalDeviceCount; ++dev) {
sorted_group_term[group].group_props.physicalDevices[dev] = sorted_group_term[group].internal_device_info[dev].physical_device;
}
}
// Sort device groups by PCI info
@@ -435,8 +441,9 @@ VkResult linux_read_sorted_physical_device_groups(struct loader_instance *inst,
for (uint32_t group = 0; group < group_count; ++group) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, " Group %u", group);
for (uint32_t gpu = 0; gpu < sorted_group_term[group].group_props.physicalDeviceCount; ++gpu) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, " [%u] %s %s", gpu,
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, " [%u] %s %p %s", gpu,
sorted_group_term[group].internal_device_info[gpu].device_name,
sorted_group_term[group].internal_device_info[gpu].physical_device,
(sorted_group_term[group].internal_device_info[gpu].default_device ? "[default]" : ""));
}
}
+14 -241
View File
@@ -724,13 +724,6 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
loader_instance_heap_free(ptr_instance, ptr_instance->phys_devs_tramp);
}
if (ptr_instance->phys_dev_groups_tramp) {
for (uint32_t i = 0; i < ptr_instance->phys_dev_group_count_tramp; i++) {
loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp[i]);
}
loader_instance_heap_free(ptr_instance, ptr_instance->phys_dev_groups_tramp);
}
if (messenger_setup) {
loader_log(ptr_instance, VULKAN_LOADER_INFO_BIT, 0,
"vkDestroyInstance: destroying temporary instance debug util messenger");
@@ -760,8 +753,6 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
VkPhysicalDevice *pPhysicalDevices) {
VkResult res = VK_SUCCESS;
uint32_t count;
uint32_t i;
struct loader_instance *inst;
loader_platform_thread_lock_mutex(&loader_lock);
@@ -784,38 +775,16 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstan
// Setup the trampoline loader physical devices. This will actually
// call down and setup the terminator loader physical devices during the
// process.
VkResult setup_res = setup_loader_tramp_phys_devs(inst);
if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) {
res = setup_res;
goto out;
}
count = inst->phys_dev_count_tramp;
if (inst->phys_dev_count_tramp != inst->total_gpu_count) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"vkEnumeratePhysicalDevices: One or more layers modified physical devices!"
"Count returned by ICDs = %d, count returned above layers = %d",
inst->total_gpu_count, inst->phys_dev_count_tramp);
}
res = inst->disp->layer_inst_disp.EnumeratePhysicalDevices(inst->instance, pPhysicalDeviceCount, pPhysicalDevices);
// Wrap the PhysDev object for loader usage, return wrapped objects
if (NULL != pPhysicalDevices) {
if (inst->phys_dev_count_tramp > *pPhysicalDeviceCount) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"vkEnumeratePhysicalDevices: Trimming device count down"
" by application request from %d to %d physical devices",
inst->phys_dev_count_tramp, *pPhysicalDeviceCount);
count = *pPhysicalDeviceCount;
res = VK_INCOMPLETE;
}
for (i = 0; i < count; i++) {
pPhysicalDevices[i] = (VkPhysicalDevice)inst->phys_devs_tramp[i];
if (NULL != pPhysicalDevices && (VK_SUCCESS == res || VK_INCOMPLETE == res)) {
VkResult update_res = setup_loader_tramp_phys_devs(inst, *pPhysicalDeviceCount, pPhysicalDevices);
if (VK_SUCCESS != update_res) {
res = update_res;
}
}
*pPhysicalDeviceCount = count;
out:
loader_platform_thread_unlock_mutex(&loader_lock);
@@ -2516,193 +2485,9 @@ LOADER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer co
// ---- Vulkan core 1.1 trampolines
VkResult setupLoaderTrampPhysDevGroups(VkInstance instance, struct loader_instance *inst) {
VkResult res = VK_SUCCESS;
uint32_t total_count = 0;
VkPhysicalDeviceGroupPropertiesKHR **new_phys_dev_groups = NULL;
VkPhysicalDeviceGroupPropertiesKHR *local_phys_dev_groups = NULL;
PFN_vkEnumeratePhysicalDeviceGroups fpEnumeratePhysicalDeviceGroups = NULL;
// Get the function pointer to use to call into the ICD. This could be the core or KHR version
if (inst->enabled_known_extensions.khr_device_group_creation) {
fpEnumeratePhysicalDeviceGroups = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroupsKHR;
} else {
fpEnumeratePhysicalDeviceGroups = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups;
}
// Setup the trampoline loader physical devices. This will actually
// call down and setup the terminator loader physical devices during the
// process.
VkResult setup_res = setup_loader_tramp_phys_devs(inst);
if (setup_res != VK_SUCCESS && setup_res != VK_INCOMPLETE) {
res = setup_res;
goto out;
}
// Query how many physical device groups there
res = fpEnumeratePhysicalDeviceGroups(inst->instance, &total_count, NULL);
if (res != VK_SUCCESS) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
"\'EnumeratePhysicalDeviceGroupsKHR\' to lower layers or "
"loader to get count.");
goto out;
}
// Create an array for the new physical device groups, which will be stored
// in the instance for the trampoline code.
new_phys_dev_groups = (VkPhysicalDeviceGroupPropertiesKHR **)loader_instance_heap_alloc(
inst, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHR *), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == new_phys_dev_groups) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed to allocate new physical device"
" group array of size %d",
total_count);
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
memset(new_phys_dev_groups, 0, total_count * sizeof(VkPhysicalDeviceGroupPropertiesKHR *));
// Create a temporary array (on the stack) to keep track of the
// returned VkPhysicalDevice values.
local_phys_dev_groups = loader_stack_alloc(sizeof(VkPhysicalDeviceGroupPropertiesKHR) * total_count);
if (NULL == local_phys_dev_groups) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed to allocate local "
"physical device group array of size %d",
total_count);
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
// Initialize the memory to something valid
memset(local_phys_dev_groups, 0, sizeof(VkPhysicalDeviceGroupPropertiesKHR) * total_count);
for (uint32_t group = 0; group < total_count; group++) {
local_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES_KHR;
local_phys_dev_groups[group].pNext = NULL;
local_phys_dev_groups[group].subsetAllocation = false;
}
// Call down and get the content
fpEnumeratePhysicalDeviceGroups(inst->instance, &total_count, local_phys_dev_groups);
if (VK_SUCCESS != res) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed during dispatch call of "
"\'EnumeratePhysicalDeviceGroupsKHR\' to lower layers or "
"loader to get content.");
goto out;
}
// Replace all the physical device IDs with the proper loader values
for (uint32_t group = 0; group < total_count; group++) {
for (uint32_t group_gpu = 0; group_gpu < local_phys_dev_groups[group].physicalDeviceCount; group_gpu++) {
bool found = false;
for (uint32_t tramp_gpu = 0; tramp_gpu < inst->phys_dev_count_tramp; tramp_gpu++) {
if (local_phys_dev_groups[group].physicalDevices[group_gpu] == inst->phys_devs_tramp[tramp_gpu]->phys_dev) {
local_phys_dev_groups[group].physicalDevices[group_gpu] = (VkPhysicalDevice)inst->phys_devs_tramp[tramp_gpu];
found = true;
break;
}
}
if (!found) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed to find GPU %d in group %d"
" returned by \'EnumeratePhysicalDeviceGroupsKHR\' in list returned"
" by \'EnumeratePhysicalDevices\'",
group_gpu, group);
res = VK_ERROR_INITIALIZATION_FAILED;
goto out;
}
}
}
// Copy or create everything to fill the new array of physical device groups
for (uint32_t new_idx = 0; new_idx < total_count; new_idx++) {
// Check if this physical device group with the same contents is already in the old buffer
for (uint32_t old_idx = 0; old_idx < inst->phys_dev_group_count_tramp; old_idx++) {
if (local_phys_dev_groups[new_idx].physicalDeviceCount == inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount) {
bool found_all_gpus = true;
for (uint32_t old_gpu = 0; old_gpu < inst->phys_dev_groups_tramp[old_idx]->physicalDeviceCount; old_gpu++) {
bool found_gpu = false;
for (uint32_t new_gpu = 0; new_gpu < local_phys_dev_groups[new_idx].physicalDeviceCount; new_gpu++) {
if (local_phys_dev_groups[new_idx].physicalDevices[new_gpu] ==
inst->phys_dev_groups_tramp[old_idx]->physicalDevices[old_gpu]) {
found_gpu = true;
break;
}
}
if (!found_gpu) {
found_all_gpus = false;
break;
}
}
if (!found_all_gpus) {
continue;
} else {
new_phys_dev_groups[new_idx] = inst->phys_dev_groups_tramp[old_idx];
break;
}
}
}
// If this physical device group isn't in the old buffer, create it
if (NULL == new_phys_dev_groups[new_idx]) {
new_phys_dev_groups[new_idx] = (VkPhysicalDeviceGroupPropertiesKHR *)loader_instance_heap_alloc(
inst, sizeof(VkPhysicalDeviceGroupPropertiesKHR), VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == new_phys_dev_groups[new_idx]) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"setupLoaderTrampPhysDevGroups: Failed to allocate "
"physical device group trampoline object %d",
new_idx);
total_count = new_idx;
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
memcpy(new_phys_dev_groups[new_idx], &local_phys_dev_groups[new_idx], sizeof(VkPhysicalDeviceGroupPropertiesKHR));
}
}
out:
if (VK_SUCCESS != res) {
if (NULL != new_phys_dev_groups) {
for (uint32_t i = 0; i < total_count; i++) {
loader_instance_heap_free(inst, new_phys_dev_groups[i]);
}
loader_instance_heap_free(inst, new_phys_dev_groups);
}
total_count = 0;
} else {
// Free everything that didn't carry over to the new array of
// physical device groups
if (NULL != inst->phys_dev_groups_tramp) {
for (uint32_t i = 0; i < inst->phys_dev_group_count_tramp; i++) {
bool found = false;
for (uint32_t j = 0; j < total_count; j++) {
if (inst->phys_dev_groups_tramp[i] == new_phys_dev_groups[j]) {
found = true;
break;
}
}
if (!found) {
loader_instance_heap_free(inst, inst->phys_dev_groups_tramp[i]);
}
}
loader_instance_heap_free(inst, inst->phys_dev_groups_tramp);
}
// Swap in the new physical device group list
inst->phys_dev_group_count_tramp = total_count;
inst->phys_dev_groups_tramp = new_phys_dev_groups;
}
return res;
}
LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
VkInstance instance, uint32_t *pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties *pPhysicalDeviceGroupProperties) {
VkResult res = VK_SUCCESS;
uint32_t count;
uint32_t i;
struct loader_instance *inst = NULL;
loader_platform_thread_lock_mutex(&loader_lock);
@@ -2723,31 +2508,19 @@ LOADER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
goto out;
}
VkResult setup_res = setupLoaderTrampPhysDevGroups(instance, inst);
if (VK_SUCCESS != setup_res) {
res = setup_res;
goto out;
}
count = inst->phys_dev_group_count_tramp;
// Setup the trampoline loader physical devices. This will actually
// call down and setup the terminator loader physical devices during the
// process.
res = inst->disp->layer_inst_disp.EnumeratePhysicalDeviceGroups(inst->instance, pPhysicalDeviceGroupCount,
pPhysicalDeviceGroupProperties);
// Wrap the PhysDev object for loader usage, return wrapped objects
if (NULL != pPhysicalDeviceGroupProperties) {
if (inst->phys_dev_group_count_tramp > *pPhysicalDeviceGroupCount) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"vkEnumeratePhysicalDeviceGroupsKHR: Trimming device group count down"
" by application request from %d to %d physical device groups",
inst->phys_dev_group_count_tramp, *pPhysicalDeviceGroupCount);
count = *pPhysicalDeviceGroupCount;
res = VK_INCOMPLETE;
}
for (i = 0; i < count; i++) {
memcpy(&pPhysicalDeviceGroupProperties[i], inst->phys_dev_groups_tramp[i], sizeof(VkPhysicalDeviceGroupPropertiesKHR));
if (NULL != pPhysicalDeviceGroupProperties && (VK_SUCCESS == res || VK_INCOMPLETE == res)) {
VkResult update_res = setup_loader_tramp_phys_dev_groups(inst, *pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
if (VK_SUCCESS != update_res) {
res = update_res;
}
}
*pPhysicalDeviceGroupCount = count;
out:
loader_platform_thread_unlock_mutex(&loader_lock);
Binary file not shown.
+2
View File
@@ -76,6 +76,8 @@ struct PhysicalDevice {
};
struct PhysicalDeviceGroup {
PhysicalDeviceGroup() {}
PhysicalDeviceGroup(PhysicalDevice const& physical_device) { physical_device_handles.push_back(&physical_device); }
PhysicalDeviceGroup& use_physical_device(PhysicalDevice const& physical_device) {
physical_device_handles.push_back(&physical_device);
return *this;
+71 -18
View File
@@ -209,25 +209,73 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDevices(VkInstance instan
// VK_SUCCESS,VK_INCOMPLETE, VK_ERROR_INITIALIZATION_FAILED
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDeviceGroups(
VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
VkResult result = VK_SUCCESS;
if (pPhysicalDeviceGroupProperties == nullptr) {
*pPhysicalDeviceGroupCount = static_cast<uint32_t>(icd.physical_device_groups.size());
} else {
for (size_t device_group = 0; device_group < icd.physical_device_groups.size(); device_group++) {
if (device_group >= *pPhysicalDeviceGroupCount) {
return VK_INCOMPLETE;
}
pPhysicalDeviceGroupProperties[device_group].subsetAllocation =
icd.physical_device_groups[device_group].subset_allocation;
uint32_t handles_written = 0;
for (size_t i = 0; i < icd.physical_device_groups[device_group].physical_device_handles.size(); i++) {
handles_written++;
pPhysicalDeviceGroupProperties[device_group].physicalDevices[i] =
icd.physical_device_groups[device_group].physical_device_handles[i]->vk_physical_device.handle;
}
pPhysicalDeviceGroupProperties[device_group].physicalDeviceCount = handles_written;
if (0 == icd.physical_device_groups.size()) {
*pPhysicalDeviceGroupCount = static_cast<uint32_t>(icd.physical_devices.size());
} else {
*pPhysicalDeviceGroupCount = static_cast<uint32_t>(icd.physical_device_groups.size());
}
} else {
// NOTE: This is a fake struct to make sure the pNext chain is properly passed down to the ICD
// vkEnumeratePhysicalDeviceGroups.
// The two versions must match:
// "FakePNext" test in loader_regresion_tests.cpp
// "test_vkEnumeratePhysicalDeviceGroups" in test_icd.cpp
struct FakePnextSharedWithICD {
VkStructureType sType;
void* pNext;
uint32_t value;
};
uint32_t group_count = 0;
if (0 == icd.physical_device_groups.size()) {
group_count = icd.physical_devices.size();
for (size_t device_group = 0; device_group < icd.physical_devices.size(); device_group++) {
if (device_group >= *pPhysicalDeviceGroupCount) {
group_count = *pPhysicalDeviceGroupCount;
result = VK_INCOMPLETE;
break;
}
pPhysicalDeviceGroupProperties[device_group].subsetAllocation = false;
pPhysicalDeviceGroupProperties[device_group].physicalDeviceCount = 1;
pPhysicalDeviceGroupProperties[device_group].physicalDevices[0] =
icd.physical_devices[device_group].vk_physical_device.handle;
}
} else {
group_count = icd.physical_device_groups.size();
for (size_t device_group = 0; device_group < icd.physical_device_groups.size(); device_group++) {
if (device_group >= *pPhysicalDeviceGroupCount) {
group_count = *pPhysicalDeviceGroupCount;
result = VK_INCOMPLETE;
break;
}
pPhysicalDeviceGroupProperties[device_group].subsetAllocation =
icd.physical_device_groups[device_group].subset_allocation;
uint32_t handles_written = 0;
for (size_t i = 0; i < icd.physical_device_groups[device_group].physical_device_handles.size(); i++) {
handles_written++;
pPhysicalDeviceGroupProperties[device_group].physicalDevices[i] =
icd.physical_device_groups[device_group].physical_device_handles[i]->vk_physical_device.handle;
}
pPhysicalDeviceGroupProperties[device_group].physicalDeviceCount = handles_written;
}
}
// NOTE: The following code is purely to test pNext passing in vkEnumeratePhysicalDevice groups
// and includes normally invalid information.
for (size_t device_group = 0; device_group < group_count; device_group++) {
if (nullptr != pPhysicalDeviceGroupProperties[device_group].pNext) {
VkBaseInStructure* base = reinterpret_cast<VkBaseInStructure*>(pPhysicalDeviceGroupProperties[device_group].pNext);
if (base->sType == VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTI_DRAW_PROPERTIES_EXT) {
FakePnextSharedWithICD* fake = reinterpret_cast<FakePnextSharedWithICD*>(base);
fake->value = 0xDECAFBAD;
}
}
}
*pPhysicalDeviceGroupCount = static_cast<uint32_t>(group_count);
}
return VK_SUCCESS;
return result;
}
VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDebugUtilsMessengerEXT(VkInstance instance,
@@ -962,6 +1010,9 @@ PFN_vkVoidFunction get_instance_func_ver_1_1(VkInstance instance, const char* pN
if (string_eq(pName, "test_vkEnumerateInstanceVersion")) {
return to_vkVoidFunction(test_vkEnumerateInstanceVersion);
}
if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups")) {
return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
}
}
return nullptr;
}
@@ -1225,8 +1276,10 @@ PFN_vkVoidFunction get_instance_func(VkInstance instance, const char* pName) {
if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
if (string_eq(pName, "vkDestroyInstance")) return to_vkVoidFunction(test_vkDestroyInstance);
if (string_eq(pName, "vkEnumeratePhysicalDevices")) return to_vkVoidFunction(test_vkEnumeratePhysicalDevices);
if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups") || string_eq(pName, "vkEnumeratePhysicalDeviceGroupsKHR"))
return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
if (IsInstanceExtensionEnabled(VK_KHR_DEVICE_GROUP_CREATION_EXTENSION_NAME)) {
if (string_eq(pName, "vkEnumeratePhysicalDeviceGroupsKHR")) return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
}
PFN_vkVoidFunction ret_phys_dev = get_physical_device_func(instance, pName);
if (ret_phys_dev != nullptr) return ret_phys_dev;
+3 -3
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 LunarG, Inc.
* Copyright (c) 2021-2022 The Khronos Group Inc.
* Copyright (c) 2021-2022 Valve Corporation
* Copyright (c) 2021-2022 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
+50 -2
View File
@@ -1,6 +1,6 @@
# ~~~
# Copyright (c) 2021 Valve Corporation
# Copyright (c) 2021 LunarG, Inc.
# Copyright (c) 2021-2022 Valve Corporation
# Copyright (c) 2021-2022 LunarG, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -27,6 +27,7 @@ target_compile_definitions(test_layer_deps INTERFACE
target_link_libraries(test_layer_deps INTERFACE testing_framework_util)
# Interface testing layer
set(TEST_LAYER_SOURCES test_layer.cpp test_layer.h)
set(TEST_LAYER_BASE_EXPORTS TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS=1)
@@ -53,6 +54,48 @@ target_link_libraries(test_layer_export_version_2 PRIVATE test_layer_deps)
target_compile_definitions(test_layer_export_version_2 PRIVATE
${TEST_LAYER_VERSION_0_EXPORTS} ${TEST_LAYER_VERSION_1_EXPORTS} ${TEST_LAYER_VERSION_2_EXPORTS} )
# Physical device list altering layer (add phys dev, remove phys dev, re-order phys devs)
set(PHYSDEV_LAYER_ADD_EXPORTS
${TEST_LAYER_VERSION_0_EXPORTS} ${TEST_LAYER_VERSION_1_EXPORTS} ${TEST_LAYER_VERSION_2_EXPORTS}
TEST_LAYER_NAME="VkLayer_LunarG_add_phys_dev"
TEST_PHYSDEV_LAYER_ADD=1
)
set(PHYSDEV_REMOVE_EXPORTS
${TEST_LAYER_VERSION_0_EXPORTS} ${TEST_LAYER_VERSION_1_EXPORTS} ${TEST_LAYER_VERSION_2_EXPORTS}
TEST_LAYER_NAME="VkLayer_LunarG_remove_phys_dev"
TEST_PHYSDEV_LAYER_REMOVE=1
)
set(PHYSDEV_LAYER_REORDER_EXPORTS
${TEST_LAYER_VERSION_0_EXPORTS} ${TEST_LAYER_VERSION_1_EXPORTS} ${TEST_LAYER_VERSION_2_EXPORTS}
TEST_LAYER_NAME="VkLayer_LunarG_reorder_phys_dev"
TEST_PHYSDEV_LAYER_REORDER=1
)
set(PHYSDEV_LAYER_ALL_EXPORTS
${TEST_LAYER_VERSION_0_EXPORTS} ${TEST_LAYER_VERSION_1_EXPORTS} ${TEST_LAYER_VERSION_2_EXPORTS}
TEST_LAYER_NAME="VkLayer_LunarG_all_phys_dev"
TEST_PHYSDEV_LAYER_ADD=1
TEST_PHYSDEV_LAYER_REMOVE=1
TEST_PHYSDEV_LAYER_REORDER=1
)
add_library(test_layer_physdev_add SHARED ${TEST_LAYER_SOURCES})
target_link_libraries(test_layer_physdev_add PRIVATE test_layer_deps)
target_compile_definitions(test_layer_physdev_add PRIVATE ${PHYSDEV_LAYER_ADD_EXPORTS})
add_library(test_layer_physdev_remove SHARED ${TEST_LAYER_SOURCES})
target_link_libraries(test_layer_physdev_remove PRIVATE test_layer_deps)
target_compile_definitions(test_layer_physdev_remove PRIVATE ${PHYSDEV_REMOVE_EXPORTS})
add_library(test_layer_physdev_reorder SHARED ${TEST_LAYER_SOURCES})
target_link_libraries(test_layer_physdev_reorder PRIVATE test_layer_deps)
target_compile_definitions(test_layer_physdev_reorder PRIVATE ${PHYSDEV_LAYER_REORDER_EXPORTS})
add_library(test_layer_physdev_all SHARED ${TEST_LAYER_SOURCES})
target_link_libraries(test_layer_physdev_all PRIVATE test_layer_deps)
target_compile_definitions(test_layer_physdev_all PRIVATE ${PHYSDEV_LAYER_ALL_EXPORTS})
# Wrap Objects layer which wraps dispatchable handles to test that the loader will properly
# work in the case where handles in the terminator don't match handles in the trampoline portion.
set(WRAP_LAYER_VERSION_1_EXPORTS
TEST_LAYER_EXPORT_DIRECT_DISP=1
TEST_LAYER_EXPORT_MAINT_1=1
@@ -83,11 +126,16 @@ add_library(test_layer_wrap_objects_3 SHARED wrap_objects)
target_link_libraries(test_layer_wrap_objects_3 PRIVATE test_layer_deps)
target_compile_definitions(test_layer_wrap_objects_3 PRIVATE ${WRAP_LAYER_VERSION_3_EXPORTS})
# Windows requires export definitions for these layers
if(WIN32)
target_sources(test_layer_export_base PRIVATE export_definitions/test_layer_base.def)
target_sources(test_layer_export_version_0 PRIVATE export_definitions/test_layer_0.def)
target_sources(test_layer_export_version_1 PRIVATE export_definitions/test_layer_1.def)
target_sources(test_layer_export_version_2 PRIVATE export_definitions/test_layer_2.def)
target_sources(test_layer_physdev_add PRIVATE export_definitions/test_layer_2.def)
target_sources(test_layer_physdev_remove PRIVATE export_definitions/test_layer_2.def)
target_sources(test_layer_physdev_reorder PRIVATE export_definitions/test_layer_2.def)
target_sources(test_layer_physdev_all PRIVATE export_definitions/test_layer_2.def)
target_sources(test_layer_wrap_objects PRIVATE export_definitions/test_layer_wrap_objects.def)
target_sources(test_layer_wrap_objects_1 PRIVATE export_definitions/test_layer_wrap_objects.def)
target_sources(test_layer_wrap_objects_2 PRIVATE export_definitions/test_layer_wrap_objects.def)
+217 -7
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 LunarG, Inc.
* Copyright (c) 2021-2022 The Khronos Group Inc.
* Copyright (c) 2021-2022 Valve Corporation
* Copyright (c) 2021-2022 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
@@ -74,6 +74,10 @@
#define LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION 0
#endif
#ifndef TEST_LAYER_NAME
#define TEST_LAYER_NAME "VkLayer_LunarG_test_layer"
#endif
TestLayer layer;
extern "C" {
FRAMEWORK_EXPORT TestLayer* get_test_layer_func() { return &layer; }
@@ -107,7 +111,7 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceLayerProperties(uint32_t*
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName && string_eq(pLayerName, layer.unique_name.c_str())) {
if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
*pPropertyCount = 0;
return VK_SUCCESS;
}
@@ -122,7 +126,7 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceLayerProperties(VkPhysicalD
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName,
uint32_t* pPropertyCount,
VkExtensionProperties* pProperties) {
if (pLayerName && string_eq(pLayerName, layer.unique_name.c_str())) {
if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
*pPropertyCount = 0;
return VK_SUCCESS;
}
@@ -171,7 +175,7 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo*
}
VKAPI_ATTR VkResult VKAPI_CALL test_override_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
return VK_ERROR_INVALID_SHADER_NV;
}
@@ -214,6 +218,195 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevi
return result;
}
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices) {
#if !TEST_PHYSDEV_LAYER_REMOVE && !TEST_PHYSDEV_LAYER_ADD && !TEST_PHYSDEV_LAYER_REORDER
return layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
#else // TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
VkResult res = VK_SUCCESS;
if (layer.complete_physical_devices.size() == 0) {
// Get list of all physical devices from lower down
// NOTE: This only works if we don't test changing the number of devices
// underneath us when using this test.
uint32_t icd_count = 0;
layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, &icd_count, nullptr);
std::vector<VkPhysicalDevice> tmp_vector;
tmp_vector.resize(icd_count);
layer.instance_dispatch_table.EnumeratePhysicalDevices(instance, &icd_count, tmp_vector.data());
layer.complete_physical_devices.clear();
#if TEST_PHYSDEV_LAYER_REMOVE
// Erase the 3rd and 4th items
layer.removed_physical_devices.push_back(tmp_vector[3]);
layer.removed_physical_devices.push_back(tmp_vector[4]);
tmp_vector.erase(tmp_vector.begin() + 3);
tmp_vector.erase(tmp_vector.begin() + 3);
#endif // TEST_PHYSDEV_LAYER_REMOVE
#if TEST_PHYSDEV_LAYER_ADD
// Insert a new device in the beginning, middle, and end
uint32_t middle = tmp_vector.size() / 2;
VkPhysicalDevice new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xABCD0000));
layer.added_physical_devices.push_back(new_phys_dev);
tmp_vector.insert(tmp_vector.begin(), new_phys_dev);
new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xBADC0000));
layer.added_physical_devices.push_back(new_phys_dev);
tmp_vector.insert(tmp_vector.begin() + middle, new_phys_dev);
new_phys_dev = reinterpret_cast<VkPhysicalDevice>((size_t)(0xDCBA0000));
layer.added_physical_devices.push_back(new_phys_dev);
tmp_vector.push_back(new_phys_dev);
#endif // TEST_PHYSDEV_LAYER_ADD
#if TEST_PHYSDEV_LAYER_REORDER
// Flip the order of items
for (int32_t dev = tmp_vector.size() - 1; dev >= 0; --dev) {
layer.complete_physical_devices.push_back(tmp_vector[dev]);
}
#else // !TEST_PHYSDEV_LAYER_REORDER
// Otherwise, keep the order the same
for (uint32_t dev = 0; dev < tmp_vector.size(); ++dev) {
layer.complete_physical_devices.push_back(tmp_vector[dev]);
}
#endif // !TEST_PHYSDEV_LAYER_REORDER
}
if (nullptr == pPhysicalDevices) {
*pPhysicalDeviceCount = layer.complete_physical_devices.size();
} else {
uint32_t adj_count = layer.complete_physical_devices.size();
if (*pPhysicalDeviceCount < adj_count) {
adj_count = *pPhysicalDeviceCount;
res = VK_INCOMPLETE;
}
for (uint32_t dev = 0; dev < adj_count; ++dev) {
pPhysicalDevices[dev] = layer.complete_physical_devices[dev];
}
*pPhysicalDeviceCount = adj_count;
}
return res;
#endif // TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
}
VKAPI_ATTR void VKAPI_CALL test_vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties) {
#if TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
if (std::find(layer.removed_physical_devices.begin(), layer.removed_physical_devices.end(), physicalDevice) !=
layer.removed_physical_devices.end()) {
// Should not get here since the application should not know about those devices
assert(false);
} else if (std::find(layer.added_physical_devices.begin(), layer.added_physical_devices.end(), physicalDevice) !=
layer.added_physical_devices.end()) {
// Added device so put in some placeholder info we can test against
pProperties->apiVersion = VK_API_VERSION_1_2;
pProperties->driverVersion = VK_MAKE_API_VERSION(0, 12, 14, 196);
pProperties->vendorID = 0xDECAFBAD;
pProperties->deviceID = 0xDEADBADD;
#if defined(_WIN32)
strncpy_s(pProperties->deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, "physdev_added_xx", 17);
#else
strncpy(pProperties->deviceName, "physdev_added_xx", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
} else {
#else // !TEST_PHYSDEV_LAYER_REMOVE && !TEST_PHYSDEV_LAYER_ADD && !TEST_PHYSDEV_LAYER_REORDER
{
#endif
// Not an affected device so just return
layer.instance_dispatch_table.GetPhysicalDeviceProperties(physicalDevice, pProperties);
}
}
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumeratePhysicalDeviceGroups(
VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
#if !TEST_PHYSDEV_LAYER_REMOVE && !TEST_PHYSDEV_LAYER_ADD && !TEST_PHYSDEV_LAYER_REORDER
return layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount,
pPhysicalDeviceGroupProperties);
#else // TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
VkResult res = VK_SUCCESS;
if (layer.complete_physical_device_groups.size() == 0) {
uint32_t fake_count = 1000;
// Call EnumerateDevices to add remove devices as needed
test_vkEnumeratePhysicalDevices(instance, &fake_count, nullptr);
// Get list of all physical devices from lower down
// NOTE: This only works if we don't test changing the number of devices
// underneath us when using this test.
uint32_t icd_group_count = 0;
layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, &icd_group_count, nullptr);
std::vector<VkPhysicalDeviceGroupProperties> tmp_vector(icd_group_count);
for (uint32_t group = 0; group < icd_group_count; ++group) {
tmp_vector[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
layer.instance_dispatch_table.EnumeratePhysicalDeviceGroups(instance, &icd_group_count, tmp_vector.data());
layer.complete_physical_device_groups.clear();
#if TEST_PHYSDEV_LAYER_REMOVE
// Now, if a device has been removed, and it was the only group, we need to remove the group as well.
for (uint32_t rem_dev = 0; rem_dev < layer.removed_physical_devices.size(); ++rem_dev) {
for (uint32_t group = 0; group < icd_group_count; ++group) {
for (uint32_t grp_dev = 0; grp_dev < tmp_vector[group].physicalDeviceCount; ++grp_dev) {
if (tmp_vector[group].physicalDevices[grp_dev] == layer.removed_physical_devices[rem_dev]) {
for (uint32_t cp_item = grp_dev + 1; cp_item < tmp_vector[group].physicalDeviceCount; ++cp_item) {
tmp_vector[group].physicalDevices[grp_dev] = tmp_vector[group].physicalDevices[cp_item];
}
tmp_vector[group].physicalDeviceCount--;
}
}
}
}
for (uint32_t group = 0; group < tmp_vector.size(); ++group) {
if (tmp_vector[group].physicalDeviceCount == 0) {
layer.removed_physical_device_groups.push_back(tmp_vector[group]);
tmp_vector.erase(tmp_vector.begin() + group);
--group;
}
}
#endif // TEST_PHYSDEV_LAYER_REMOVE
#if TEST_PHYSDEV_LAYER_ADD
// Add a new group for each physical device not associated with a current group
for (uint32_t dev = 0; dev < layer.added_physical_devices.size(); ++dev) {
VkPhysicalDeviceGroupProperties props{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES};
props.physicalDeviceCount = 1;
props.physicalDevices[0] = layer.added_physical_devices[dev];
tmp_vector.push_back(props);
layer.added_physical_device_groups.push_back(props);
}
#endif // TEST_PHYSDEV_LAYER_ADD
#if TEST_PHYSDEV_LAYER_REORDER
// Flip the order of items
for (int32_t dev = tmp_vector.size() - 1; dev >= 0; --dev) {
layer.complete_physical_device_groups.push_back(tmp_vector[dev]);
}
#else // !TEST_PHYSDEV_LAYER_REORDER
// Otherwise, keep the order the same
for (uint32_t dev = 0; dev < tmp_vector.size(); ++dev) {
layer.complete_physical_device_groups.push_back(tmp_vector[dev]);
}
#endif // !TEST_PHYSDEV_LAYER_REORDER
}
if (nullptr == pPhysicalDeviceGroupProperties) {
*pPhysicalDeviceGroupCount = layer.complete_physical_device_groups.size();
} else {
uint32_t adj_count = layer.complete_physical_device_groups.size();
if (*pPhysicalDeviceGroupCount < adj_count) {
adj_count = *pPhysicalDeviceGroupCount;
res = VK_INCOMPLETE;
}
for (uint32_t dev = 0; dev < adj_count; ++dev) {
pPhysicalDeviceGroupProperties[dev] = layer.complete_physical_device_groups[dev];
}
*pPhysicalDeviceGroupCount = adj_count;
}
return res;
#endif // TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
}
// device functions
VKAPI_ATTR void VKAPI_CALL test_vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
@@ -244,6 +437,9 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance,
if (string_eq(pName, "vkEnumerateDeviceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateDeviceLayerProperties);
if (string_eq(pName, "vkEnumerateDeviceExtensionProperties"))
return to_vkVoidFunction(test_vkEnumerateDeviceExtensionProperties);
if (string_eq(pName, "vkEnumeratePhysicalDevices")) return to_vkVoidFunction(test_vkEnumeratePhysicalDevices);
if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups")) return to_vkVoidFunction(test_vkEnumeratePhysicalDeviceGroups);
if (string_eq(pName, "vkGetPhysicalDeviceProperties")) return to_vkVoidFunction(test_vkGetPhysicalDeviceProperties);
if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_vkCreateInstance);
if (string_eq(pName, "vkDestroyInstance")) return to_vkVoidFunction(test_vkDestroyInstance);
if (string_eq(pName, "vkCreateDevice")) return to_vkVoidFunction(test_vkCreateDevice);
@@ -326,13 +522,27 @@ FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProper
VkExtensionProperties* pProperties) {
return test_vkEnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount, pProperties);
}
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(VkInstance instance, uint32_t* pPhysicalDeviceCount,
VkPhysicalDevice* pPhysicalDevices) {
return test_vkEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
}
FRAMEWORK_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceProperties* pProperties) {
return test_vkGetPhysicalDeviceProperties(physicalDevice, pProperties);
}
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDeviceGroups(
VkInstance instance, uint32_t* pPhysicalDeviceGroupCount, VkPhysicalDeviceGroupProperties* pPhysicalDeviceGroupProperties) {
return test_vkEnumeratePhysicalDeviceGroups(instance, pPhysicalDeviceGroupCount, pPhysicalDeviceGroupProperties);
}
#endif
#if TEST_LAYER_EXPORT_LAYER_NAMED_GIPA
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_layer_GetInstanceProcAddr(VkInstance instance, const char* pName) {
return get_instance_func(instance, pName);
}
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_override_vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_override_vkGetInstanceProcAddr(VkInstance instance,
const char* pName) {
if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_override_vkCreateInstance);
return get_instance_func(instance, pName);
}
+26 -4
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 LunarG, Inc.
* Copyright (c) 2021-2022 The Khronos Group Inc.
* Copyright (c) 2021-2022 Valve Corporation
* Copyright (c) 2021-2022 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
@@ -80,6 +80,21 @@ Interface Version 2
// Added manifest version 1.1.0
// vkEnumeratePhysicalDevices and vkEnumeratePhysicalDeviceGroups add a new item
#ifndef TEST_PHYSDEV_LAYER_ADD
#define TEST_PHYSDEV_LAYER_ADD 0
#endif
// vkEnumeratePhysicalDevices and vkEnumeratePhysicalDeviceGroups remove an item
#ifndef TEST_PHYSDEV_LAYER_REMOVE
#define TEST_PHYSDEV_LAYER_REMOVE 0
#endif
// vkEnumeratePhysicalDevices and vkEnumeratePhysicalDeviceGroups reorders items
#ifndef TEST_PHYSDEV_LAYER_REORDER
#define TEST_PHYSDEV_LAYER_REORDER 0
#endif
struct TestLayer;
// Callbacks allow tests to implement custom functionality without modifying the layer binary
@@ -94,7 +109,6 @@ struct TestLayer {
BUILDER_VALUE(TestLayer, bool, is_meta_layer, false)
BUILDER_VALUE(TestLayer, std::string, unique_name, {})
BUILDER_VALUE(TestLayer, uint32_t, api_version, VK_API_VERSION_1_0)
BUILDER_VALUE(TestLayer, uint32_t, reported_layer_props, 1)
BUILDER_VALUE(TestLayer, uint32_t, reported_extension_props, 1)
@@ -119,6 +133,14 @@ struct TestLayer {
BUILDER_VALUE(TestLayer, std::function<VkResult(TestLayer& layer)>, create_instance_callback, {})
// Called in vkCreateDevice after calling down the chain & returning
BUILDER_VALUE(TestLayer, std::function<VkResult(TestLayer& layer)>, create_device_callback, {})
#if TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
BUILDER_VECTOR(TestLayer, VkPhysicalDevice, complete_physical_devices, complete_physical_device)
BUILDER_VECTOR(TestLayer, VkPhysicalDevice, removed_physical_devices, removed_physical_device)
BUILDER_VECTOR(TestLayer, VkPhysicalDevice, added_physical_devices, added_physical_device)
BUILDER_VECTOR(TestLayer, VkPhysicalDeviceGroupProperties, complete_physical_device_groups, complete_physical_device_group)
BUILDER_VECTOR(TestLayer, VkPhysicalDeviceGroupProperties, removed_physical_device_groups, removed_physical_device_group)
BUILDER_VECTOR(TestLayer, VkPhysicalDeviceGroupProperties, added_physical_device_groups, added_physical_device_group)
#endif // TEST_PHYSDEV_LAYER_REMOVE || TEST_PHYSDEV_LAYER_ADD || TEST_PHYSDEV_LAYER_REORDER
PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr = VK_NULL_HANDLE;
PFN_GetPhysicalDeviceProcAddr next_GetPhysicalDeviceProcAddr = VK_NULL_HANDLE;
+13 -2
View File
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2015-2021 Valve Corporation
* Copyright (c) 2015-2021 LunarG, Inc.
* Copyright (c) 2015-2022 Valve Corporation
* Copyright (c) 2015-2022 LunarG, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -425,14 +425,25 @@ VKAPI_ATTR VkResult VKAPI_CALL wrap_vkEnumerateDeviceExtensionProperties(VkPhysi
ext_count = 0;
#if TEST_LAYER_EXPORT_MAINT_1
if (ext_count < count) {
#if defined(_WIN32)
strncpy_s(pProperties[ext_count].extensionName, VK_MAX_EXTENSION_NAME_SIZE, VK_KHR_MAINTENANCE1_EXTENSION_NAME,
strlen(VK_KHR_MAINTENANCE1_EXTENSION_NAME) + 1);
#else
strcpy(pProperties[ext_count].extensionName, VK_KHR_MAINTENANCE1_EXTENSION_NAME);
#endif
pProperties[ext_count].specVersion = 2;
ext_count++;
}
#endif
#if TEST_LAYER_EXPORT_PRESENT_IMAGE
if (ext_count < count) {
#if defined(_WIN32)
strncpy_s(pProperties[ext_count].extensionName, VK_MAX_EXTENSION_NAME_SIZE,
VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME,
strlen(VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME) + 1);
#else
strcpy(pProperties[ext_count].extensionName, VK_KHR_SHARED_PRESENTABLE_IMAGE_EXTENSION_NAME);
#endif
pProperties[ext_count].specVersion = 1;
ext_count++;
}
+1 -1
View File
@@ -782,7 +782,7 @@ TEST_F(SeparateMessenger, InfoInEnumDevsIgnoredSeverity) {
}
// Test debug utils created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices.
TEST_F(SeparateMessenger, DebugUtilsInfoInEnumDevs) {
TEST_F(SeparateMessenger, InfoInEnumDevs) {
expected_message = "Trimming device count down by application request";
expected_object_type = VK_OBJECT_TYPE_INSTANCE;
expected_message_flags = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT;
+545 -3
View File
@@ -1,7 +1,7 @@
/*
* Copyright (c) 2021 The Khronos Group Inc.
* Copyright (c) 2021 Valve Corporation
* Copyright (c) 2021 LunarG, Inc.
* Copyright (c) 2021-2022 The Khronos Group Inc.
* Copyright (c) 2021-2022 Valve Corporation
* Copyright (c) 2021-2022 LunarG, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and/or associated documentation files (the "Materials"), to
@@ -45,6 +45,7 @@ class LayerExtensions : public LayerTests {};
class MetaLayers : public LayerTests {};
class OverrideMetaLayer : public LayerTests {};
class LayerCreateInstance : public LayerTests {};
class LayerPhysDeviceMod : public LayerTests {};
void CheckLogForLayerString(FrameworkEnvironment& env, const char* implicit_layer_name, bool check_for_enable) {
{
@@ -2776,3 +2777,544 @@ TEST(TestLayers, DeviceLayerNotPresent) {
dev.create_info.add_layer(explicit_layer_name);
dev.CheckCreate(phys_dev);
}
TEST_F(LayerPhysDeviceMod, AddPhysicalDevices) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_add_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_ADD)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_ADD_PHYS_DEV")),
"test_layer_remove.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_devices = 6;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t dev_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &dev_count, nullptr));
ASSERT_GT(dev_count, icd_devices);
auto not_exp_physical_devices = std::vector<VkPhysicalDevice>(icd_devices);
uint32_t returned_phys_dev_count = icd_devices;
ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, not_exp_physical_devices.data()));
ASSERT_EQ(icd_devices, returned_phys_dev_count);
auto physical_devices = std::vector<VkPhysicalDevice>(dev_count);
returned_phys_dev_count = dev_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
ASSERT_EQ(dev_count, returned_phys_dev_count);
uint32_t diff_count = dev_count - icd_devices;
uint32_t found_incomplete = 0;
uint32_t found_added_count = 0;
for (uint32_t dev = 0; dev < dev_count; ++dev) {
VkPhysicalDeviceProperties props{};
inst->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
if (string_eq(props.deviceName, "physdev_added_xx")) {
found_added_count++;
}
for (uint32_t incomp = 0; incomp < icd_devices; ++incomp) {
if (not_exp_physical_devices[incomp] == physical_devices[dev]) {
found_incomplete++;
break;
}
}
}
// We should have added the number of diff items, and the incomplete count should match the number of
// original physical devices.
ASSERT_EQ(found_added_count, diff_count);
ASSERT_EQ(found_incomplete, icd_devices);
}
TEST_F(LayerPhysDeviceMod, RemovePhysicalDevices) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_remove_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_REMOVE)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_REMOVE_PHYS_DEV")),
"test_layer_remove.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_devices = 6;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t dev_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &dev_count, nullptr));
ASSERT_LT(dev_count, icd_devices);
auto physical_devices = std::vector<VkPhysicalDevice>(dev_count);
uint32_t returned_phys_dev_count = dev_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
ASSERT_EQ(dev_count, returned_phys_dev_count);
}
TEST_F(LayerPhysDeviceMod, ReorderPhysicalDevices) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_reorder_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_REORDER)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_REORDER_PHYS_DEV")),
"test_layer_reorder.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_devices = 6;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t dev_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &dev_count, nullptr));
ASSERT_EQ(dev_count, icd_devices);
auto physical_devices = std::vector<VkPhysicalDevice>(dev_count);
uint32_t returned_phys_dev_count = dev_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
ASSERT_EQ(dev_count, returned_phys_dev_count);
}
TEST_F(LayerPhysDeviceMod, AddRemoveAndReorderPhysicalDevices) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_all_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_ALL)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_ALL_PHYS_DEV")),
"test_layer_all.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_devices = 6;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t dev_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &dev_count, nullptr));
ASSERT_GT(dev_count, icd_devices);
auto physical_devices = std::vector<VkPhysicalDevice>(dev_count);
uint32_t returned_phys_dev_count = dev_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDevices(inst, &returned_phys_dev_count, physical_devices.data()));
ASSERT_EQ(dev_count, returned_phys_dev_count);
uint32_t found_added_count = 0;
for (uint32_t dev = 0; dev < dev_count; ++dev) {
VkPhysicalDeviceProperties props{};
inst->vkGetPhysicalDeviceProperties(physical_devices[dev], &props);
if (string_eq(props.deviceName, "physdev_added_xx")) {
found_added_count++;
}
}
// Should see 2 removed, but 3 added so a diff count of 1
uint32_t diff_count = dev_count - icd_devices;
ASSERT_EQ(1, diff_count);
ASSERT_EQ(found_added_count, 3);
}
static bool GroupsAreTheSame(VkPhysicalDeviceGroupProperties a, VkPhysicalDeviceGroupProperties b) {
if (a.physicalDeviceCount != b.physicalDeviceCount) {
return false;
}
for (uint32_t dev = 0; dev < a.physicalDeviceCount; ++dev) {
if (a.physicalDevices[dev] != b.physicalDevices[dev]) {
return false;
}
}
return true;
}
TEST_F(LayerPhysDeviceMod, AddPhysicalDeviceGroups) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_add_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_ADD)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_ADD_PHYS_DEV")),
"test_layer_remove.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_groups = 4;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t grp_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &grp_count, nullptr));
ASSERT_GT(grp_count, icd_groups);
auto not_exp_phys_dev_groups = std::vector<VkPhysicalDeviceGroupProperties>(icd_groups);
for (uint32_t group = 0; group < icd_groups; ++group) {
not_exp_phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
uint32_t returned_group_count = icd_groups;
ASSERT_EQ(VK_INCOMPLETE, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, not_exp_phys_dev_groups.data()));
ASSERT_EQ(icd_groups, returned_group_count);
auto phys_dev_groups = std::vector<VkPhysicalDeviceGroupProperties>(grp_count);
for (uint32_t group = 0; group < grp_count; ++group) {
phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
returned_group_count = grp_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, phys_dev_groups.data()));
ASSERT_EQ(grp_count, returned_group_count);
uint32_t diff_count = grp_count - icd_groups;
uint32_t found_incomplete = 0;
uint32_t found_added_count = 0;
for (uint32_t grp = 0; grp < grp_count; ++grp) {
// Shortcut, only groups with 1 device could be added in the newly added count
if (1 == phys_dev_groups[grp].physicalDeviceCount) {
for (uint32_t dev = 0; dev < phys_dev_groups[grp].physicalDeviceCount; ++dev) {
VkPhysicalDeviceProperties props{};
inst->vkGetPhysicalDeviceProperties(phys_dev_groups[grp].physicalDevices[dev], &props);
if (string_eq(props.deviceName, "physdev_added_xx")) {
found_added_count++;
}
}
}
for (uint32_t incomp = 0; incomp < icd_groups; ++incomp) {
if (GroupsAreTheSame(not_exp_phys_dev_groups[incomp], phys_dev_groups[grp])) {
found_incomplete++;
break;
}
}
}
// We should have added the number of diff items, and the incomplete count should match the number of
// original physical devices.
ASSERT_EQ(found_added_count, diff_count);
ASSERT_EQ(found_incomplete, icd_groups);
}
TEST_F(LayerPhysDeviceMod, RemovePhysicalDeviceGroups) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_remove_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_REMOVE)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_REMOVE_PHYS_DEV")),
"test_layer_remove.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_groups = 4;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t grp_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &grp_count, nullptr));
ASSERT_LT(grp_count, icd_groups);
auto phys_dev_groups = std::vector<VkPhysicalDeviceGroupProperties>(grp_count);
for (uint32_t group = 0; group < grp_count; ++group) {
phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
uint32_t returned_group_count = grp_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, phys_dev_groups.data()));
ASSERT_EQ(grp_count, returned_group_count);
}
TEST_F(LayerPhysDeviceMod, ReorderPhysicalDeviceGroups) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_reorder_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_REORDER)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_REORDER_PHYS_DEV")),
"test_layer_reorder.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_groups = 4;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t grp_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &grp_count, nullptr));
ASSERT_EQ(grp_count, icd_groups);
auto phys_dev_groups = std::vector<VkPhysicalDeviceGroupProperties>(grp_count);
for (uint32_t group = 0; group < grp_count; ++group) {
phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
uint32_t returned_group_count = grp_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, phys_dev_groups.data()));
ASSERT_EQ(grp_count, returned_group_count);
}
TEST_F(LayerPhysDeviceMod, AddRemoveAndReorderPhysicalDeviceGroups) {
FrameworkEnvironment env;
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VkLayer_LunarG_all_phys_dev")
.set_lib_path(TEST_LAYER_PHYSDEV_ALL)
.set_api_version(VK_API_VERSION_1_1)
.set_disable_environment("TEST_DISABLE_ALL_PHYS_DEV")),
"test_layer_all.json");
for (uint32_t icd = 0; icd < 2; ++icd) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
auto& cur_icd = env.get_test_icd(icd);
cur_icd.icd_api_version = VK_API_VERSION_1_2;
VkPhysicalDeviceProperties properties{};
properties.apiVersion = VK_API_VERSION_1_2;
properties.vendorID = 0x11000000 + (icd << 6);
char vendor_char = 'a' + icd;
for (uint32_t dev = 0; dev < 3; ++dev) {
properties.deviceID = properties.vendorID + dev;
properties.deviceType = VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU;
char dev_char = '0' + dev;
std::string dev_name = "physdev_";
dev_name += vendor_char;
dev_name += "_";
dev_name += dev_char;
#if defined(_WIN32)
strncpy_s(properties.deviceName, VK_MAX_PHYSICAL_DEVICE_NAME_SIZE, dev_name.c_str(), dev_name.length() + 1);
#else
strncpy(properties.deviceName, dev_name.c_str(), VK_MAX_PHYSICAL_DEVICE_NAME_SIZE);
#endif
cur_icd.add_physical_device({});
cur_icd.physical_devices.back().set_properties(properties);
}
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[0]);
cur_icd.physical_device_groups.emplace_back(cur_icd.physical_devices[1]);
cur_icd.physical_device_groups.back().use_physical_device(cur_icd.physical_devices[2]);
}
const uint32_t icd_groups = 4;
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(VK_API_VERSION_1_1);
inst.CheckCreate();
uint32_t grp_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &grp_count, nullptr));
ASSERT_GT(grp_count, icd_groups);
auto phys_dev_groups = std::vector<VkPhysicalDeviceGroupProperties>(grp_count);
for (uint32_t group = 0; group < grp_count; ++group) {
phys_dev_groups[group].sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES;
}
uint32_t returned_group_count = grp_count;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, phys_dev_groups.data()));
ASSERT_EQ(grp_count, returned_group_count);
uint32_t diff_count = grp_count - icd_groups;
uint32_t found_added_count = 0;
for (uint32_t grp = 0; grp < grp_count; ++grp) {
// Shortcut, only groups with 1 device could be added in the newly added count
if (1 == phys_dev_groups[grp].physicalDeviceCount) {
for (uint32_t dev = 0; dev < phys_dev_groups[grp].physicalDeviceCount; ++dev) {
VkPhysicalDeviceProperties props{};
inst->vkGetPhysicalDeviceProperties(phys_dev_groups[grp].physicalDevices[dev], &props);
if (string_eq(props.deviceName, "physdev_added_xx")) {
found_added_count++;
}
}
}
}
// Should see 2 devices removed which should result in 1 group removed and since 3
// devices were added we should have 3 new groups. So we should have a diff of 2
// groups and 3 new groups
ASSERT_EQ(2, diff_count);
ASSERT_EQ(found_added_count, 3);
}
File diff suppressed because it is too large Load Diff
+89 -1
View File
@@ -320,6 +320,94 @@ TEST(MultipleDriverConfig, DifferentICDInterfaceVersions) {
ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
ASSERT_EQ(phys_dev_count, 2);
}
TEST(MultipleDriverConfig, DifferentICDsWithDevices) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
// Make sure the loader returns all devices from all active ICDs. Many of the other
// tests add multiple devices to a single ICD, this just makes sure the loader combines
// device info across multiple drivers properly.
TestICD& icd0 = env.get_test_icd(0);
icd0.physical_devices.emplace_back("physical_device_0");
icd0.min_icd_interface_version = 5;
icd0.max_icd_interface_version = 5;
TestICD& icd1 = env.get_test_icd(1);
icd1.physical_devices.emplace_back("physical_device_1");
icd1.physical_devices.emplace_back("physical_device_2");
icd1.min_icd_interface_version = 5;
icd1.max_icd_interface_version = 5;
TestICD& icd2 = env.get_test_icd(2);
icd2.physical_devices.emplace_back("physical_device_3");
icd2.min_icd_interface_version = 5;
icd2.max_icd_interface_version = 5;
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
std::array<VkPhysicalDevice, 4> phys_devs_array;
uint32_t phys_dev_count = 4;
ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &phys_dev_count, phys_devs_array.data()), VK_SUCCESS);
ASSERT_EQ(phys_dev_count, 4);
}
TEST(MultipleDriverConfig, DifferentICDsWithDevicesAndGroups) {
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_EXPORT_ICD_GIPA));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2));
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
// The loader has to be able to handle drivers that support device groups in combination
// with drivers that don't support device groups. When this is the case, the loader needs
// to take every driver that doesn't support device groups and put each of its devices in
// a separate group. Then it combines that information with the drivers that support
// device groups returned info.
// ICD 0 : No 1.1 support (so 1 device will become 1 group in loader)
TestICD& icd0 = env.get_test_icd(0);
icd0.physical_devices.emplace_back("physical_device_0");
icd0.min_icd_interface_version = 5;
icd0.max_icd_interface_version = 5;
icd0.set_icd_api_version(VK_API_VERSION_1_0);
// ICD 1 : 1.1 support (with 1 group with 2 devices)
TestICD& icd1 = env.get_test_icd(1);
icd1.physical_devices.emplace_back("physical_device_1");
icd1.physical_devices.emplace_back("physical_device_2");
icd1.physical_device_groups.emplace_back(icd1.physical_devices[0]);
icd1.physical_device_groups.back().use_physical_device(icd1.physical_devices[1]);
icd1.min_icd_interface_version = 5;
icd1.max_icd_interface_version = 5;
icd1.set_icd_api_version(VK_API_VERSION_1_1);
// ICD 2 : No 1.1 support (so 3 devices will become 3 groups in loader)
TestICD& icd2 = env.get_test_icd(2);
icd2.physical_devices.emplace_back("physical_device_3");
icd2.physical_devices.emplace_back("physical_device_4");
icd2.physical_devices.emplace_back("physical_device_5");
icd2.min_icd_interface_version = 5;
icd2.max_icd_interface_version = 5;
icd2.set_icd_api_version(VK_API_VERSION_1_0);
InstWrapper inst{env.vulkan_functions};
inst.create_info.set_api_version(1, 1, 0);
inst.CheckCreate();
uint32_t group_count = static_cast<uint32_t>(5);
uint32_t returned_group_count = 0;
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, nullptr));
ASSERT_EQ(group_count, returned_group_count);
std::vector<VkPhysicalDeviceGroupProperties> group_props{};
group_props.resize(group_count, VkPhysicalDeviceGroupProperties{VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GROUP_PROPERTIES});
ASSERT_EQ(VK_SUCCESS, inst->vkEnumeratePhysicalDeviceGroups(inst, &returned_group_count, group_props.data()));
ASSERT_EQ(group_count, returned_group_count);
}
// shim function pointers for 1.3
// Should use autogen for this - it generates 'shim' functions for validation layers, maybe that could be used here.
void test_vkCmdBeginRendering(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo* pRenderPassBegin,
@@ -668,4 +756,4 @@ TEST(LayerManifest, ExplicitNonVulkanVariant) {
inst.CheckCreate(VK_ERROR_LAYER_NOT_PRESENT);
ASSERT_TRUE(log.find(std::string("Layer ") + explicit_layer_name +
" has an \'api_version\' field which contains a non-zero variant value of 1. Skipping Layer."));
}
}