Files
third_party_vulkan-loader/tests/framework/layer/test_layer.cpp
T
Mark Young d4701211de 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.
2022-02-16 08:29:42 -07:00

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"