mirror of
https://github.com/openharmony/third_party_vulkan-loader.git
synced 2026-07-21 04:25:25 -04:00
d4701211de
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.
618 lines
29 KiB
C++
618 lines
29 KiB
C++
/*
|
|
* 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
|
|
* deal in the Materials without restriction, including without limitation the
|
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
|
* sell copies of the Materials, and to permit persons to whom the Materials are
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice(s) and this permission notice shall be included in
|
|
* all copies or substantial portions of the Materials.
|
|
*
|
|
* THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
*
|
|
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
|
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
|
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
|
|
* USE OR OTHER DEALINGS IN THE MATERIALS.
|
|
*
|
|
* Author: Charles Giessen <charles@lunarg.com>
|
|
*/
|
|
|
|
#include "test_layer.h"
|
|
|
|
#include "loader/generated/vk_dispatch_table_helper.h"
|
|
|
|
// export the enumeration functions instance|device+layer|extension
|
|
#ifndef TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS
|
|
#define TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS 0
|
|
#endif
|
|
|
|
// export test_layer_GetInstanceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_LAYER_NAMED_GIPA
|
|
#define TEST_LAYER_EXPORT_LAYER_NAMED_GIPA 0
|
|
#endif
|
|
|
|
// export vkGetInstanceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_LAYER_VK_GIPA
|
|
#define TEST_LAYER_EXPORT_LAYER_VK_GIPA 0
|
|
#endif
|
|
|
|
// export test_layer_GetDeviceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_LAYER_NAMED_GDPA
|
|
#define TEST_LAYER_EXPORT_LAYER_NAMED_GDPA 0
|
|
#endif
|
|
|
|
// export vkGetDeviceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_LAYER_VK_GDPA
|
|
#define TEST_LAYER_EXPORT_LAYER_VK_GDPA 0
|
|
#endif
|
|
|
|
// export GetInstanceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_NO_PREFIX_GIPA
|
|
#define TEST_LAYER_EXPORT_NO_PREFIX_GIPA 0
|
|
#endif
|
|
|
|
// export GetDeviceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_NO_PREFIX_GDPA
|
|
#define TEST_LAYER_EXPORT_NO_PREFIX_GDPA 0
|
|
#endif
|
|
|
|
// export vk_layerGetPhysicalDeviceProcAddr
|
|
#ifndef TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
|
|
#define TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR 0
|
|
#endif
|
|
|
|
// export vkNegotiateLoaderLayerInterfaceVersion
|
|
#ifndef LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION
|
|
#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; }
|
|
FRAMEWORK_EXPORT TestLayer* reset_layer_func() {
|
|
layer.~TestLayer();
|
|
return new (&layer) TestLayer();
|
|
}
|
|
}
|
|
|
|
VkLayerInstanceCreateInfo* get_chain_info(const VkInstanceCreateInfo* pCreateInfo, VkLayerFunction func) {
|
|
VkLayerInstanceCreateInfo* chain_info = (VkLayerInstanceCreateInfo*)pCreateInfo->pNext;
|
|
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
|
|
chain_info = (VkLayerInstanceCreateInfo*)chain_info->pNext;
|
|
}
|
|
assert(chain_info != NULL);
|
|
return chain_info;
|
|
}
|
|
|
|
VkLayerDeviceCreateInfo* get_chain_info(const VkDeviceCreateInfo* pCreateInfo, VkLayerFunction func) {
|
|
VkLayerDeviceCreateInfo* chain_info = (VkLayerDeviceCreateInfo*)pCreateInfo->pNext;
|
|
while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
|
|
chain_info = (VkLayerDeviceCreateInfo*)chain_info->pNext;
|
|
}
|
|
assert(chain_info != NULL);
|
|
return chain_info;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceExtensionProperties(const char* pLayerName, uint32_t* pPropertyCount,
|
|
VkExtensionProperties* pProperties) {
|
|
if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
|
|
*pPropertyCount = 0;
|
|
return VK_SUCCESS;
|
|
}
|
|
return layer.instance_dispatch_table.EnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t* pPropertyCount,
|
|
VkLayerProperties* pProperties) {
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice, const char* pLayerName,
|
|
uint32_t* pPropertyCount,
|
|
VkExtensionProperties* pProperties) {
|
|
if (pLayerName && string_eq(pLayerName, TEST_LAYER_NAME)) {
|
|
*pPropertyCount = 0;
|
|
return VK_SUCCESS;
|
|
}
|
|
return layer.instance_dispatch_table.EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pPropertyCount,
|
|
pProperties);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkEnumerateInstanceVersion(uint32_t* pApiVersion) {
|
|
if (pApiVersion != nullptr) {
|
|
*pApiVersion = VK_API_VERSION_1_0;
|
|
}
|
|
return VK_SUCCESS;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
|
|
const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
|
|
VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
|
|
|
|
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
|
|
PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
|
|
if (fpCreateInstance == NULL) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
layer.next_vkGetInstanceProcAddr = fpGetInstanceProcAddr;
|
|
layer.next_GetPhysicalDeviceProcAddr =
|
|
reinterpret_cast<PFN_GetPhysicalDeviceProcAddr>(fpGetInstanceProcAddr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr"));
|
|
|
|
// Advance the link info for the next element of the chain
|
|
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
|
|
|
|
// Continue call down the chain
|
|
VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
|
|
if (result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
layer.instance_handle = *pInstance;
|
|
|
|
// Init layer's dispatch table using GetInstanceProcAddr of
|
|
// next layer in the chain.
|
|
layer_init_instance_dispatch_table(layer.instance_handle, &layer.instance_dispatch_table, fpGetInstanceProcAddr);
|
|
|
|
if (layer.create_instance_callback) result = layer.create_instance_callback(layer);
|
|
|
|
return result;
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_override_vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo,
|
|
const VkAllocationCallbacks* pAllocator, VkInstance* pInstance) {
|
|
return VK_ERROR_INVALID_SHADER_NV;
|
|
}
|
|
|
|
VKAPI_ATTR void VKAPI_CALL test_vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator) {
|
|
layer.instance_dispatch_table.DestroyInstance(instance, pAllocator);
|
|
}
|
|
|
|
VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo,
|
|
const VkAllocationCallbacks* pAllocator, VkDevice* pDevice) {
|
|
VkLayerDeviceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
|
|
|
|
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
|
|
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
|
|
PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(layer.instance_handle, "vkCreateDevice");
|
|
if (fpCreateDevice == NULL) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
layer.next_vkGetDeviceProcAddr = fpGetDeviceProcAddr;
|
|
|
|
// Advance the link info for the next element on the chain
|
|
chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
|
|
|
|
VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
|
|
if (result != VK_SUCCESS) {
|
|
return result;
|
|
}
|
|
TestLayer::Device device{*pDevice};
|
|
|
|
// initialize layer's dispatch table
|
|
layer_init_device_dispatch_table(device.device_handle, &device.dispatch_table, fpGetDeviceProcAddr);
|
|
|
|
if (layer.create_device_callback) {
|
|
result = layer.create_device_callback(layer);
|
|
}
|
|
|
|
// Need to add the created devices to the list so it can be freed
|
|
layer.created_devices.push_back(device);
|
|
|
|
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) {
|
|
for (auto& created_device : layer.created_devices) {
|
|
if (created_device.device_handle == device) {
|
|
created_device.dispatch_table.DestroyDevice(device, pAllocator);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
// trampolines
|
|
|
|
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func(VkDevice device, const char* pName) {
|
|
if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
|
|
|
|
return layer.next_vkGetDeviceProcAddr(device, pName);
|
|
}
|
|
|
|
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName) {
|
|
if (pName == nullptr) return nullptr;
|
|
if (string_eq(pName, "vkGetInstanceProcAddr")) return to_vkVoidFunction(get_instance_func);
|
|
if (string_eq(pName, "vkEnumerateInstanceLayerProperties")) return to_vkVoidFunction(test_vkEnumerateInstanceLayerProperties);
|
|
if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
|
|
return to_vkVoidFunction(test_vkEnumerateInstanceExtensionProperties);
|
|
if (string_eq(pName, "vkEnumerateInstanceVersion")) return to_vkVoidFunction(test_vkEnumerateInstanceVersion);
|
|
|
|
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);
|
|
if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(get_device_func);
|
|
|
|
return layer.next_vkGetInstanceProcAddr(instance, pName);
|
|
}
|
|
|
|
// Exported functions
|
|
extern "C" {
|
|
#if TEST_LAYER_EXPORT_ENUMERATE_FUNCTIONS
|
|
|
|
// Pre-instance handling functions
|
|
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL test_preinst_vkEnumerateInstanceLayerProperties(
|
|
const VkEnumerateInstanceLayerPropertiesChain* pChain, uint32_t* pPropertyCount, VkLayerProperties* pProperties) {
|
|
VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pPropertyCount, pProperties);
|
|
if (nullptr == pProperties) {
|
|
*pPropertyCount = layer.reported_layer_props;
|
|
} else {
|
|
uint32_t count = layer.reported_layer_props;
|
|
if (*pPropertyCount < layer.reported_layer_props) {
|
|
count = *pPropertyCount;
|
|
res = VK_INCOMPLETE;
|
|
}
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
snprintf(pProperties[i].layerName, VK_MAX_EXTENSION_NAME_SIZE, "%02d_layer", count);
|
|
pProperties[i].specVersion = count;
|
|
pProperties[i].implementationVersion = 0xABCD0000 + count;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL test_preinst_vkEnumerateInstanceExtensionProperties(
|
|
const VkEnumerateInstanceExtensionPropertiesChain* pChain, const char* pLayerName, uint32_t* pPropertyCount,
|
|
VkExtensionProperties* pProperties) {
|
|
VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pLayerName, pPropertyCount, pProperties);
|
|
if (nullptr == pProperties) {
|
|
*pPropertyCount = layer.reported_extension_props;
|
|
} else {
|
|
uint32_t count = layer.reported_extension_props;
|
|
if (*pPropertyCount < layer.reported_extension_props) {
|
|
count = *pPropertyCount;
|
|
res = VK_INCOMPLETE;
|
|
}
|
|
for (uint32_t i = 0; i < count; ++i) {
|
|
snprintf(pProperties[i].extensionName, VK_MAX_EXTENSION_NAME_SIZE, "%02d_ext", count);
|
|
pProperties[i].specVersion = count;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
|
|
test_preinst_vkEnumerateInstanceVersion(const VkEnumerateInstanceVersionChain* pChain, uint32_t* pApiVersion) {
|
|
VkResult res = pChain->pfnNextLayer(pChain->pNextLink, pApiVersion);
|
|
*pApiVersion = layer.reported_instance_version;
|
|
return res;
|
|
}
|
|
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t* pPropertyCount,
|
|
VkLayerProperties* pProperties) {
|
|
return test_vkEnumerateInstanceLayerProperties(pPropertyCount, pProperties);
|
|
}
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char* pLayerName,
|
|
uint32_t* pPropertyCount,
|
|
VkExtensionProperties* pProperties) {
|
|
return test_vkEnumerateInstanceExtensionProperties(pLayerName, pPropertyCount, pProperties);
|
|
}
|
|
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice,
|
|
uint32_t* pPropertyCount,
|
|
VkLayerProperties* pProperties) {
|
|
return test_vkEnumerateDeviceLayerProperties(physicalDevice, pPropertyCount, pProperties);
|
|
}
|
|
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
|
|
const char* pLayerName,
|
|
uint32_t* pPropertyCount,
|
|
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) {
|
|
if (string_eq(pName, "vkCreateInstance")) return to_vkVoidFunction(test_override_vkCreateInstance);
|
|
return get_instance_func(instance, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_LAYER_VK_GIPA
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* pName) {
|
|
return get_instance_func(instance, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_LAYER_NAMED_GDPA
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL test_layer_GetDeviceProcAddr(VkDevice device, const char* pName) {
|
|
return get_device_func(device, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_LAYER_VK_GDPA
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* pName) {
|
|
return get_device_func(device, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_NO_PREFIX_GIPA
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* pName) {
|
|
return get_instance_func(instance, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_NO_PREFIX_GDPA
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* pName) {
|
|
return get_device_func(device, pName);
|
|
}
|
|
#endif
|
|
|
|
#if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
|
|
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
|
|
const char* pName) {
|
|
return layer.next_GetPhysicalDeviceProcAddr(instance, pName);
|
|
}
|
|
#endif
|
|
|
|
#if LAYER_EXPORT_NEGOTIATE_LOADER_LAYER_INTERFACE_VERSION
|
|
// vk_layer.h has a forward declaration of vkNegotiateLoaderLayerInterfaceVersion, which doesn't have any attributes
|
|
// Since FRAMEWORK_EXPORT adds __declspec(dllexport), we can't do that here, thus we need our own macro
|
|
#if (defined(__GNUC__) && (__GNUC__ >= 4)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590))
|
|
#define EXPORT_NEGOTIATE_FUNCTION __attribute__((visibility("default")))
|
|
#else
|
|
#define EXPORT_NEGOTIATE_FUNCTION
|
|
#endif
|
|
|
|
EXPORT_NEGOTIATE_FUNCTION VKAPI_ATTR VkResult VKAPI_CALL
|
|
vkNegotiateLoaderLayerInterfaceVersion(VkNegotiateLayerInterface* pVersionStruct) {
|
|
if (pVersionStruct) {
|
|
if (pVersionStruct->loaderLayerInterfaceVersion < layer.min_implementation_version) {
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
|
|
pVersionStruct->loaderLayerInterfaceVersion = layer.implementation_version;
|
|
pVersionStruct->pfnGetInstanceProcAddr = get_instance_func;
|
|
pVersionStruct->pfnGetDeviceProcAddr = get_device_func;
|
|
#if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
|
|
pVersionStruct->pfnGetPhysicalDeviceProcAddr = vk_layerGetPhysicalDeviceProcAddr;
|
|
#else
|
|
pVersionStruct->pfnGetPhysicalDeviceProcAddr = nullptr;
|
|
#endif
|
|
|
|
return VK_SUCCESS;
|
|
}
|
|
return VK_ERROR_INITIALIZATION_FAILED;
|
|
}
|
|
#endif
|
|
} // extern "C"
|