Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/Vulkan-Loader.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles Giessen <charles@lunarg.com>2022-07-22 19:04:04 +0300
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>2022-09-01 21:23:17 +0300
commit4f79db3afe55fff14ecf2b8b26f1a2bdc5b2dcf5 (patch)
treeae200ca59bc336747d6b01584baa9f434502b6a4
parent1f2f222f6034b0f38f57bf6e3bd161509122249f (diff)
Refactor unknown function tests
Allow multiple layers to intercept an unknown function and then create a single test which tests many common combinations.
-rw-r--r--tests/framework/icd/physical_device.h7
-rw-r--r--tests/framework/icd/test_icd.cpp8
-rw-r--r--tests/framework/icd/test_icd.h3
-rw-r--r--tests/framework/layer/test_layer.cpp69
-rw-r--r--tests/framework/layer/test_layer.h29
-rw-r--r--tests/framework/test_environment.h13
-rw-r--r--tests/framework/test_util.h11
-rw-r--r--tests/loader_threading_tests.cpp10
-rw-r--r--tests/loader_unknown_ext_tests.cpp1338
-rw-r--r--tests/loader_version_tests.cpp73
10 files changed, 1165 insertions, 396 deletions
diff --git a/tests/framework/icd/physical_device.h b/tests/framework/icd/physical_device.h
index cd0c97faa..fbe5cb14f 100644
--- a/tests/framework/icd/physical_device.h
+++ b/tests/framework/icd/physical_device.h
@@ -69,6 +69,11 @@ struct PhysicalDevice {
std::vector<DispatchableHandle<VkQueue>> queue_handles;
+ // Unknown physical device functions. Add a `VulkanFunction` to this list which will be searched in
+ // vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for custom_physical_device_functions.
+ // To add unknown device functions, add it to the PhysicalDevice directly (in the known_device_functions member)
+ BUILDER_VECTOR(PhysicalDevice, VulkanFunction, custom_physical_device_functions, custom_physical_device_function)
+
// List of function names which are 'known' to the physical device but have test defined implementations
// The purpose of this list is so that vkGetDeviceProcAddr returns 'a real function pointer' in tests
// without actually implementing any of the logic inside of it.
@@ -88,4 +93,4 @@ struct PhysicalDeviceGroup {
std::vector<PhysicalDevice const*> physical_device_handles;
VkBool32 subset_allocation = false;
-}; \ No newline at end of file
+};
diff --git a/tests/framework/icd/test_icd.cpp b/tests/framework/icd/test_icd.cpp
index c618d68d1..41790db88 100644
--- a/tests/framework/icd/test_icd.cpp
+++ b/tests/framework/icd/test_icd.cpp
@@ -1241,9 +1241,11 @@ PFN_vkVoidFunction get_physical_device_func(VkInstance instance, const char* pNa
return to_vkVoidFunction(test_vkGetPhysicalDeviceToolPropertiesEXT);
}
- for (auto& func : icd.custom_physical_device_functions) {
- if (func.name == pName) {
- return to_vkVoidFunction(func.function);
+ for (auto& phys_dev : icd.physical_devices) {
+ for (auto& func : phys_dev.custom_physical_device_functions) {
+ if (func.name == pName) {
+ return to_vkVoidFunction(func.function);
+ }
}
}
return nullptr;
diff --git a/tests/framework/icd/test_icd.h b/tests/framework/icd/test_icd.h
index 14bf4554d..6acdab142 100644
--- a/tests/framework/icd/test_icd.h
+++ b/tests/framework/icd/test_icd.h
@@ -80,11 +80,10 @@ struct TestICD {
std::vector<uint64_t> messenger_handles;
std::vector<uint64_t> swapchain_handles;
- // Unknown instance and physical device functions. Add a `VulkanFunction` to this list which will be searched in
+ // Unknown instance functions Add a `VulkanFunction` to this list which will be searched in
// vkGetInstanceProcAddr for custom_instance_functions and vk_icdGetPhysicalDeviceProcAddr for custom_physical_device_functions.
// To add unknown device functions, add it to the PhysicalDevice directly (in the known_device_functions member)
BUILDER_VECTOR(TestICD, VulkanFunction, custom_instance_functions, custom_instance_function)
- BUILDER_VECTOR(TestICD, VulkanFunction, custom_physical_device_functions, custom_physical_device_function)
// Must explicitely state support for the tooling info extension, that way we can control if vkGetInstanceProcAddr returns a
// function pointer for vkGetPhysicalDeviceToolPropertiesEXT or vkGetPhysicalDeviceToolProperties (core version)
diff --git a/tests/framework/layer/test_layer.cpp b/tests/framework/layer/test_layer.cpp
index f4a43bd17..0ccb1f6d8 100644
--- a/tests/framework/layer/test_layer.cpp
+++ b/tests/framework/layer/test_layer.cpp
@@ -146,6 +146,7 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo*
VkLayerInstanceCreateInfo* chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
+ PFN_vk_icdGetPhysicalDeviceProcAddr fpGetPhysicalDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetPhysicalDeviceProcAddr;
PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
if (fpCreateInstance == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
@@ -161,15 +162,28 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo*
return result;
}
layer.instance_handle = *pInstance;
- layer.next_GetPhysicalDeviceProcAddr =
- reinterpret_cast<PFN_GetPhysicalDeviceProcAddr>(fpGetInstanceProcAddr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr"));
-
+ if (layer.use_gipa_GetPhysicalDeviceProcAddr) {
+ layer.next_GetPhysicalDeviceProcAddr =
+ reinterpret_cast<PFN_GetPhysicalDeviceProcAddr>(fpGetInstanceProcAddr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr"));
+ } else {
+ layer.next_GetPhysicalDeviceProcAddr = fpGetPhysicalDeviceProcAddr;
+ }
// 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);
+ for (auto& func : layer.custom_physical_device_interception_functions) {
+ auto next_func = layer.next_GetPhysicalDeviceProcAddr(*pInstance, func.name.c_str());
+ layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
+ }
+
+ for (auto& func : layer.custom_device_interception_functions) {
+ auto next_func = layer.next_vkGetInstanceProcAddr(*pInstance, func.name.c_str());
+ layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
+ }
+
if (layer.do_spurious_allocations_in_create_instance && pAllocator && pAllocator->pfnAllocation) {
layer.spurious_instance_memory_allocation =
pAllocator->pfnAllocation(pAllocator->pUserData, 100, 8, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
@@ -221,6 +235,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevi
// initialize layer's dispatch table
layer_init_device_dispatch_table(device.device_handle, &device.dispatch_table, fpGetDeviceProcAddr);
+ for (auto& func : layer.custom_device_interception_functions) {
+ auto next_func = layer.next_vkGetDeviceProcAddr(*pDevice, func.name.c_str());
+ layer.custom_dispatch_functions.at(func.name.c_str()) = next_func;
+ }
+
if (layer.create_device_callback) {
result = layer.create_device_callback(layer);
}
@@ -453,9 +472,29 @@ FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDev
#endif
// trampolines
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func(VkDevice device, const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func_impl(VkDevice device, const char* pName) {
+ if (string_eq(pName, "vkGetDeviceProcAddr")) return to_vkVoidFunction(get_device_func);
+ if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
+
+ for (auto& func : layer.custom_device_interception_functions) {
+ if (func.name == pName) {
+ return to_vkVoidFunction(func.function);
+ }
+ }
+
+ for (auto& func : layer.custom_device_implementation_functions) {
+ if (func.name == pName) {
+ return to_vkVoidFunction(func.function);
+ }
+ }
+
+ return nullptr;
+}
VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_device_func(VkDevice device, const char* pName) {
- if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
+ PFN_vkVoidFunction ret_dev = get_device_func_impl(device, pName);
+ if (ret_dev != nullptr) return ret_dev;
return layer.next_vkGetDeviceProcAddr(device, pName);
}
@@ -468,7 +507,13 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_physical_device_func(VkInstance ins
if (string_eq(pName, "vkEnumeratePhysicalDeviceGroups")) return (PFN_vkVoidFunction)test_vkEnumeratePhysicalDeviceGroups;
if (string_eq(pName, "vkGetPhysicalDeviceProperties")) return (PFN_vkVoidFunction)test_vkGetPhysicalDeviceProperties;
- for (auto& func : layer.custom_physical_device_functions) {
+ for (auto& func : layer.custom_physical_device_interception_functions) {
+ if (func.name == pName) {
+ return to_vkVoidFunction(func.function);
+ }
+ }
+
+ for (auto& func : layer.custom_physical_device_implementation_functions) {
if (func.name == pName) {
return to_vkVoidFunction(func.function);
}
@@ -479,8 +524,8 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_physical_device_func(VkInstance ins
#endif
return nullptr;
}
-
-VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName) {
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName);
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func_impl(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);
@@ -495,6 +540,16 @@ VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance,
PFN_vkVoidFunction ret_phys_dev = get_physical_device_func(instance, pName);
if (ret_phys_dev != nullptr) return ret_phys_dev;
+ PFN_vkVoidFunction ret_dev = get_device_func_impl(nullptr, pName);
+ if (ret_dev != nullptr) return ret_dev;
+
+ return nullptr;
+}
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL get_instance_func(VkInstance instance, const char* pName) {
+ PFN_vkVoidFunction ret_dev = get_instance_func_impl(instance, pName);
+ if (ret_dev != nullptr) return ret_dev;
+
return layer.next_vkGetInstanceProcAddr(instance, pName);
}
diff --git a/tests/framework/layer/test_layer.h b/tests/framework/layer/test_layer.h
index a99a3bb3b..2d3571b43 100644
--- a/tests/framework/layer/test_layer.h
+++ b/tests/framework/layer/test_layer.h
@@ -131,7 +131,31 @@ struct TestLayer {
BUILDER_VECTOR(TestLayer, VkPhysicalDeviceGroupProperties, removed_physical_device_groups, removed_physical_device_group)
BUILDER_VECTOR(TestLayer, VkPhysicalDeviceGroupProperties, added_physical_device_groups, added_physical_device_group)
- BUILDER_VECTOR(TestLayer, VulkanFunction, custom_physical_device_functions, custom_physical_device_function)
+ BUILDER_VECTOR(TestLayer, VulkanFunction, custom_physical_device_implementation_functions,
+ custom_physical_device_implementation_function)
+ BUILDER_VECTOR(TestLayer, VulkanFunction, custom_device_implementation_functions, custom_device_implementation_function)
+
+ // Only need a single map for all 'custom' function - assumes that all function names are distinct, IE there cannot be a
+ // physical device and device level function with the same name
+ std::unordered_map<std::string, PFN_vkVoidFunction> custom_dispatch_functions;
+ std::vector<VulkanFunction> custom_physical_device_interception_functions;
+ TestLayer& add_custom_physical_device_intercept_function(std::string func_name, PFN_vkVoidFunction function) {
+ custom_physical_device_interception_functions.push_back({func_name, function});
+ custom_dispatch_functions[func_name] = nullptr;
+ return *this;
+ }
+ std::vector<VulkanFunction> custom_device_interception_functions;
+ TestLayer& add_custom_device_interception_function(std::string func_name, PFN_vkVoidFunction function) {
+ custom_device_interception_functions.push_back({func_name, function});
+ custom_dispatch_functions[func_name] = nullptr;
+ return *this;
+ }
+ PFN_vkVoidFunction get_custom_intercept_function(const char* name) {
+ if (custom_dispatch_functions.count(name) > 0) {
+ return custom_dispatch_functions.at(name);
+ }
+ return nullptr;
+ }
BUILDER_VALUE(TestLayer, bool, do_spurious_allocations_in_create_instance, false)
void* spurious_instance_memory_allocation = nullptr;
@@ -142,6 +166,9 @@ struct TestLayer {
};
std::vector<DeviceMemAlloc> spurious_device_memory_allocations;
+ // By default query GPDPA from GIPA, don't use value given from pNext
+ BUILDER_VALUE(TestLayer, bool, use_gipa_GetPhysicalDeviceProcAddr, true)
+
PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr = VK_NULL_HANDLE;
PFN_GetPhysicalDeviceProcAddr next_GetPhysicalDeviceProcAddr = VK_NULL_HANDLE;
PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr = VK_NULL_HANDLE;
diff --git a/tests/framework/test_environment.h b/tests/framework/test_environment.h
index a9259138d..dbd9d71f0 100644
--- a/tests/framework/test_environment.h
+++ b/tests/framework/test_environment.h
@@ -169,6 +169,7 @@ struct DeviceWrapper {
// Convenience
operator VkDevice() { return dev; }
+ operator VkDevice() const { return dev; }
VulkanFunctions* operator->() { return functions; }
FromVoidStarFunc load(const char* func_name) { return FromVoidStarFunc(functions->vkGetDeviceProcAddr(dev, func_name)); }
@@ -303,12 +304,12 @@ struct TestLayerHandle {
};
enum class ManifestDiscoveryType {
- generic, // put the manifest in the regular locations
- none, // don't add to regular locations - eg D3DKMT
- env_var, // use the corresponding env-var for it
- add_env_var, // use the corresponding add-env-var for it
- override_folder, // add to a special folder for the override layer to use
- windows_app_package, // let the app package search find it
+ generic, // put the manifest in the regular locations
+ none, // don't add to regular locations - eg D3DKMT
+ env_var, // use the corresponding env-var for it
+ add_env_var, // use the corresponding add-env-var for it
+ override_folder, // add to a special folder for the override layer to use
+ windows_app_package, // let the app package search find it
};
struct TestICDDetails {
diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h
index 70f8cfa45..37791c265 100644
--- a/tests/framework/test_util.h
+++ b/tests/framework/test_util.h
@@ -247,9 +247,9 @@ inline void copy_string_to_char_array(std::string const& src, char* dst, size_t
#if defined(WIN32)
// Convert an UTF-16 wstring to an UTF-8 string
-std::string narrow(const std::wstring &utf16);
+std::string narrow(const std::wstring& utf16);
// Convert an UTF-8 string to an UTF-16 wstring
-std::wstring widen(const std::string &utf8);
+std::wstring widen(const std::string& utf8);
#endif
#if defined(WIN32)
@@ -752,11 +752,11 @@ struct VulkanFunctions {
VulkanFunctions();
- FromVoidStarFunc load(VkInstance inst, const char* func_name) {
+ FromVoidStarFunc load(VkInstance inst, const char* func_name) const {
return FromVoidStarFunc(vkGetInstanceProcAddr(inst, func_name));
}
- FromVoidStarFunc load(VkDevice device, const char* func_name) {
+ FromVoidStarFunc load(VkDevice device, const char* func_name) const {
return FromVoidStarFunc(vkGetDeviceProcAddr(device, func_name));
}
};
@@ -844,8 +844,9 @@ inline bool operator!=(const VkExtensionProperties& a, const VkExtensionProperti
struct VulkanFunction {
std::string name;
- void* function;
+ PFN_vkVoidFunction function;
};
+
template <typename T, size_t U>
bool check_permutation(std::initializer_list<const char*> expected, std::array<T, U> const& returned) {
if (expected.size() != returned.size()) return false;
diff --git a/tests/loader_threading_tests.cpp b/tests/loader_threading_tests.cpp
index 946944c63..78999a04b 100644
--- a/tests/loader_threading_tests.cpp
+++ b/tests/loader_threading_tests.cpp
@@ -77,14 +77,14 @@ TEST(ThreadingTests, ConcurentGetDeviceProcAddr) {
driver.physical_devices.emplace_back("physical_device_0");
driver.physical_devices.back().known_device_functions.push_back(
- {"vkCmdBindPipeline", reinterpret_cast<void*>(test_vkCmdBindPipeline)});
+ {"vkCmdBindPipeline", to_vkVoidFunction(test_vkCmdBindPipeline)});
driver.physical_devices.back().known_device_functions.push_back(
- {"vkCmdBindDescriptorSets", reinterpret_cast<void*>(test_vkCmdBindDescriptorSets)});
+ {"vkCmdBindDescriptorSets", to_vkVoidFunction(test_vkCmdBindDescriptorSets)});
driver.physical_devices.back().known_device_functions.push_back(
- {"vkCmdBindVertexBuffers", reinterpret_cast<void*>(test_vkCmdBindVertexBuffers)});
+ {"vkCmdBindVertexBuffers", to_vkVoidFunction(test_vkCmdBindVertexBuffers)});
driver.physical_devices.back().known_device_functions.push_back(
- {"vkCmdBindIndexBuffer", reinterpret_cast<void*>(test_vkCmdBindIndexBuffer)});
- driver.physical_devices.back().known_device_functions.push_back({"vkCmdDraw", reinterpret_cast<void*>(test_vkCmdDraw)});
+ {"vkCmdBindIndexBuffer", to_vkVoidFunction(test_vkCmdBindIndexBuffer)});
+ driver.physical_devices.back().known_device_functions.push_back({"vkCmdDraw", to_vkVoidFunction(test_vkCmdDraw)});
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
diff --git a/tests/loader_unknown_ext_tests.cpp b/tests/loader_unknown_ext_tests.cpp
index 492eec393..294251afe 100644
--- a/tests/loader_unknown_ext_tests.cpp
+++ b/tests/loader_unknown_ext_tests.cpp
@@ -27,11 +27,24 @@
#include "test_environment.h"
#include <functional>
+#include <tuple>
+
+enum class TestConfig {
+ add_layer_implementation,
+ add_layer_interception,
+};
+
+bool has_flag(std::vector<TestConfig> const& flags, TestConfig config) {
+ for (auto const& flag : flags)
+ if (flag == config) return true;
+ return false;
+}
/*
- Creates a TestICD with a function unknown to the loader called vkNotRealFuncTEST. The TestICD, when vk_icdGetPhysicalDeviceProcAddr
- is called, will return the custom_physical_device_function if the function name matches vkNotRealFuncTEST. The test then calls the
- function to verify that the unknown physical device function dispatching is working correctly.
+ Creates a TestICD with a function unknown to the loader called vkNotRealFuncTEST. The TestICD, when
+ vk_icdGetPhysicalDeviceProcAddr is called, will return the custom_physical_device_function if the function name matches
+ vkNotRealFuncTEST. The test then calls the function to verify that the unknown physical device function dispatching is
+ working correctly.
*/
template <typename DispatchableHandleType>
struct custom_functions {
@@ -47,56 +60,282 @@ struct custom_functions {
};
};
-template <typename FunctionStruct>
-void fill_custom_functions(std::vector<VulkanFunction>& driver_function_list, std::vector<std::string>& fake_function_names,
- FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0) {
- for (uint32_t i = function_start; i < function_start + function_count;) {
- fake_function_names.push_back(std::string("vkNotIntRealFuncTEST_") + std::to_string(i++));
- driver_function_list.push_back(VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_zero)});
+/*
+Functions for testing of layer interception of unknown functions. Note the need to pass a pointer to the layer and the name
+of the called function as a parameter, this is necessary to allow a generic layer implementation, as the layer must look up
+the function pointer to use. A real layer would store the function pointer in a dedicated structure per-instance/device, but
+since the TestLayer is a generic layer, there isn't a fixed list of functions that should be supported.
+*/
+
+PFN_vkVoidFunction find_custom_func(TestLayer* layer, const char* name) {
+ if (layer->custom_dispatch_functions.count(name) > 0) {
+ return layer->custom_dispatch_functions.at(name);
+ }
+ return nullptr;
+}
+
+template <typename DispatchableHandleType>
+struct layer_intercept_functions {
+ static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i) {
+ auto func = reinterpret_cast<decltype(&func_zero)>(find_custom_func(layer, name));
+ if (func == nullptr) return 1337;
+ return func(handle, layer, name, i + 3);
+ }
+ static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t i,
+ float f) {
+ auto func = reinterpret_cast<decltype(&func_one)>(find_custom_func(layer, name));
+ if (func == nullptr) return 1337;
+ return func(handle, layer, name, i + 2, f + 1.f);
+ }
+ static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t foo,
+ uint32_t bar, float baz) {
+ auto func = reinterpret_cast<decltype(&func_two)>(find_custom_func(layer, name));
+ if (func == nullptr) return -1337;
+ return func(handle, layer, name, foo + 1, bar + 2, baz * 2);
+ };
+ static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
+ int* ptr_b) {
+ auto func = reinterpret_cast<decltype(&func_three)>(find_custom_func(layer, name));
+ if (func == nullptr) return -1337;
+ *ptr_a += 1;
+ *ptr_b -= 2;
+ return func(handle, layer, name, ptr_a, ptr_b);
+ };
+ static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
+ int* ptr_b, int foo, int bar, float k, float l, char a, char b, char c) {
+ auto func = reinterpret_cast<decltype(&func_four)>(find_custom_func(layer, name));
+ if (func == nullptr) return -1337.f;
+ return func(handle, layer, name, ptr_a, ptr_b, foo + 4, bar + 5, k + 1, l + 2, 'd', 'e', 'f');
+ };
+};
- fake_function_names.push_back(std::string("vkNotIntRealIntFuncTEST_") + std::to_string(i++));
- driver_function_list.push_back(VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_one)});
+template <typename DispatchableHandleType>
+struct layer_implementation_functions {
+ static VKAPI_ATTR uint32_t VKAPI_CALL func_zero(DispatchableHandleType device, TestLayer* layer, const char* name, uint32_t i) {
+ return i * 3;
+ }
+ static VKAPI_ATTR uint32_t VKAPI_CALL func_one(DispatchableHandleType device, TestLayer* layer, const char* name, uint32_t i,
+ float f) {
+ return static_cast<int>(i * 3 + f * 10.f);
+ }
+ static VKAPI_ATTR float VKAPI_CALL func_two(DispatchableHandleType handle, TestLayer* layer, const char* name, uint32_t foo,
+ uint32_t bar, float baz) {
+ return baz + foo + bar;
+ };
+ static VKAPI_ATTR int VKAPI_CALL func_three(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
+ int* ptr_b) {
+ return *ptr_a + *ptr_b;
+ };
+ static VKAPI_ATTR float VKAPI_CALL func_four(DispatchableHandleType handle, TestLayer* layer, const char* name, int* ptr_a,
+ int* ptr_b, int foo, int bar, float k, float l, char a, char b, char c) {
+ return *ptr_a + *ptr_b + foo + bar + k + l + static_cast<int>(a) + static_cast<int>(b) + static_cast<int>(c);
+ };
+};
- fake_function_names.push_back(std::string("vkIntNotIntRealFloatFuncTEST_") + std::to_string(i++));
- driver_function_list.push_back(VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_two)});
+// Add function_count strings to the func_names vector, starting at function_start place. Essentially a utility for filling
+// up a list of names to use later
+void add_function_names(std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ func_names.push_back(std::string("vkNotIntRealFuncTEST_") + std::to_string(i++));
+ func_names.push_back(std::string("vkNotIntRealIntFuncTEST_") + std::to_string(i++));
+ func_names.push_back(std::string("vkIntNotIntRealFloatFuncTEST_") + std::to_string(i++));
+ func_names.push_back(std::string("vkNotRealFuncPointerPointerTEST_") + std::to_string(i++));
+ func_names.push_back(std::string("vkNotRealFuncTEST_pointer_pointer_int_int_float_float_char_char_char_") +
+ std::to_string(i++));
+ }
+}
- fake_function_names.push_back(std::string("vkNotRealFuncPointerPointerTEST_") + std::to_string(i++));
- driver_function_list.push_back(VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_three)});
+// Add data to the function_list, which could be a driver or a layer list of implementation functions.
+template <typename FunctionStruct>
+void fill_implementation_functions(std::vector<VulkanFunction>& function_list, std::vector<std::string>& func_names,
+ FunctionStruct const& funcs, uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_zero)});
+ function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_one)});
+ function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_two)});
+ function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_three)});
+ function_list.push_back(VulkanFunction{func_names.at(i++), to_vkVoidFunction(funcs.func_four)});
+ }
+}
- fake_function_names.push_back(std::string("vkNotRealFuncTEST_pointer_pointer_int_int_float_float_char_char_char_") +
- std::to_string(i++));
- driver_function_list.push_back(VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_four)});
+// Add device interception functions to a layer. Need to call `add_custom_device_interception_function` since the layer has
+// to setup a unordered_map for storing the next function in the chain, and key it based on the name
+template <typename FunctionStruct>
+void fill_device_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
+ uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
+ layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
+ layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
+ layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
+ layer.add_custom_device_interception_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
}
}
+// Add physical device interception functions to a layer. Need to call `add_custom_device_interception_function` since the
+// layer has to setup a unordered_map for storing the next function in the chain, and key it based on the name
+template <typename FunctionStruct>
+void fill_phys_dev_intercept_functions(TestLayer& layer, std::vector<std::string>& func_names, FunctionStruct const& funcs,
+ uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_zero));
+ layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_one));
+ layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_two));
+ layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_three));
+ layer.add_custom_physical_device_intercept_function(func_names.at(i++), to_vkVoidFunction(funcs.func_four));
+ }
+}
+
template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
void check_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, FunctionStruct const& s,
- std::vector<std::string>& fake_function_names, uint32_t function_count, uint32_t function_start = 0) {
+ std::vector<std::string>& func_names, uint32_t function_count, uint32_t function_start = 0) {
for (uint32_t i = function_start; i < function_start + function_count;) {
- decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, fake_function_names.at(i++).c_str());
+ decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i++).c_str());
ASSERT_NE(returned_func_i, nullptr);
EXPECT_EQ(returned_func_i(handle, i * 10), i * 10);
- decltype(FunctionStruct::func_one)* returned_func_ii = loader.load(parent, fake_function_names.at(i++).c_str());
+ decltype(FunctionStruct::func_one)* returned_func_ii = loader.load(parent, func_names.at(i++).c_str());
ASSERT_NE(returned_func_ii, nullptr);
EXPECT_EQ(returned_func_ii(handle, i * 10, i * 5), i * 10 + i * 5);
- decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, fake_function_names.at(i++).c_str());
+ decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i++).c_str());
ASSERT_NE(returned_func_iif, nullptr);
EXPECT_NEAR(returned_func_iif(handle, i * 10, i * 5, 0.1234f), i * 10 + i * 5 + 0.1234f, 0.001);
int x = 5;
int y = -505;
- decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, fake_function_names.at(i++).c_str());
+ decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i++).c_str());
ASSERT_NE(returned_func_pp, nullptr);
EXPECT_EQ(returned_func_pp(handle, &x, &y), -500);
- decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, fake_function_names.at(i++).c_str());
+ x = 5;
+ y = -505;
+ decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i++).c_str());
ASSERT_NE(returned_func_ppiiffccc, nullptr);
EXPECT_NEAR(returned_func_ppiiffccc(handle, &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
-500 + 200 + 300 + 0.123 + 1001.89 + 97 + 98 + 99, 0.001f);
}
}
+
+template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
+void check_layer_custom_functions(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle, TestLayer& layer,
+ FunctionStruct const& s, std::vector<std::string>& func_names, uint32_t function_count,
+ uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_i, nullptr);
+ EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i + 3) * 3);
+ i++;
+ decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_if, nullptr);
+ EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i + 2) * 3 + (i + 2) * 10);
+ i++;
+
+ decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_iif, nullptr);
+ EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
+ (i * 10 + 1) + (i * 5 + 2) + (0.1234f * 2.f), 0.001);
+ i++;
+
+ int x = 5 + i;
+ int y = -505 - i;
+ decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_pp, nullptr);
+ EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
+ (5 + static_cast<int>(i) + 1) + (-505 - static_cast<int>(i) - 2));
+ i++;
+
+ x = 5;
+ y = -505;
+ decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_ppiiffccc, nullptr);
+ EXPECT_NEAR(
+ returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
+ -500 + (200 + 4) + (300 + 5) + (0.123 + 1) + (1001.89 + 2) + 100 + 101 + 102,
+ 0.001f); // layer changes abc to def
+ i++;
+ }
+}
+
+template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
+void check_layer_custom_functions_no_implementation(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
+ TestLayer& layer, FunctionStruct const& s, std::vector<std::string>& func_names,
+ uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_i, nullptr);
+ EXPECT_EQ(1337U, returned_func_i(handle, &layer, func_names.at(i).c_str(), i));
+ i++;
+ decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_if, nullptr);
+ EXPECT_EQ(1337U, returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f));
+ i++;
+
+ decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_iif, nullptr);
+ EXPECT_NEAR(-1337.0, returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f), 0.001);
+ i++;
+
+ int x = 5 + i;
+ int y = -505 - i;
+ decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_pp, nullptr);
+ EXPECT_EQ(-1337, returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y));
+ i++;
+
+ x = 5;
+ y = -505;
+ decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_ppiiffccc, nullptr);
+ EXPECT_NEAR(
+ -1337.0,
+ returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
+ 0.001);
+ i++;
+ }
+}
+
+template <typename FunctionLoader, typename ParentType, typename DispatchableHandleType, typename FunctionStruct>
+void check_layer_custom_functions_no_interception(FunctionLoader& loader, ParentType parent, DispatchableHandleType handle,
+ TestLayer& layer, FunctionStruct const& s, std::vector<std::string>& func_names,
+ uint32_t function_count, uint32_t function_start = 0) {
+ for (uint32_t i = function_start; i < function_start + function_count;) {
+ decltype(FunctionStruct::func_zero)* returned_func_i = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_i, nullptr);
+ EXPECT_EQ(returned_func_i(handle, &layer, func_names.at(i).c_str(), i), (i)*3);
+ i++;
+ decltype(FunctionStruct::func_one)* returned_func_if = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_if, nullptr);
+ EXPECT_EQ(returned_func_if(handle, &layer, func_names.at(i).c_str(), i, i + 1.f), (i)*3 + (i + 1) * 10);
+ i++;
+
+ decltype(FunctionStruct::func_two)* returned_func_iif = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_iif, nullptr);
+ EXPECT_NEAR(returned_func_iif(handle, &layer, func_names.at(i).c_str(), i * 10, i * 5, 0.1234f),
+ (i * 10) + (i * 5) + (0.1234f), 0.001);
+ i++;
+
+ int x = 5 + i;
+ int y = -505 - i;
+ decltype(FunctionStruct::func_three)* returned_func_pp = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_pp, nullptr);
+ EXPECT_EQ(returned_func_pp(handle, &layer, func_names.at(i).c_str(), &x, &y),
+ (5 + static_cast<int>(i)) + (-505 - static_cast<int>(i)));
+ i++;
+
+ x = 5;
+ y = -505;
+ decltype(FunctionStruct::func_four)* returned_func_ppiiffccc = loader.load(parent, func_names.at(i).c_str());
+ ASSERT_NE(returned_func_ppiiffccc, nullptr);
+ EXPECT_NEAR(
+ returned_func_ppiiffccc(handle, &layer, func_names.at(i).c_str(), &x, &y, 200, 300, 0.123f, 1001.89f, 'a', 'b', 'c'),
+ -500 + (200) + (300) + (0.123) + (1001.89) + 97 + 98 + 99, 0.001f);
+ i++;
+ }
+}
+
using custom_physical_device_functions = custom_functions<VkPhysicalDevice>;
+using layer_intercept_physical_device_functions = layer_intercept_functions<VkPhysicalDevice>;
+using layer_implementation_physical_device_functions = layer_implementation_functions<VkPhysicalDevice>;
TEST(UnknownFunction, PhysicalDeviceFunction) {
#if defined(__APPLE__)
@@ -104,18 +343,19 @@ TEST(UnknownFunction, PhysicalDeviceFunction) {
#endif
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
- std::vector<std::string> fake_function_names;
+ uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
driver.physical_devices.emplace_back("physical_device_0");
- fill_custom_functions(driver.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{},
- function_count);
+ fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
+ custom_physical_device_functions{}, function_count);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, fake_function_names,
+ check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, function_names,
function_count);
}
@@ -128,7 +368,9 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
auto& driver_0 = env.get_test_icd(0);
auto& driver_1 = env.get_test_icd(1);
- std::vector<std::string> fake_function_names;
+ uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
// used to identify the GPUs
VkPhysicalDeviceProperties props{};
@@ -139,11 +381,11 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
props.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
driver_1.physical_devices.back().set_properties(props);
- for (uint32_t i = 0; i < 25; i++) {
- fill_custom_functions(driver_0.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10);
- fill_custom_functions(driver_1.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10 + 5);
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
+ custom_physical_device_functions{}, 5, i * 10);
+ fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
+ custom_physical_device_functions{}, 5, i * 10 + 5);
}
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
@@ -156,11 +398,11 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupport) {
phys_dev_0 = phys_devs[1];
phys_dev_1 = phys_devs[0];
}
- for (uint32_t i = 0; i < 25; i++) {
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, fake_function_names,
- 5, i * 10);
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, fake_function_names,
- 5, i * 10 + 5);
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
+ i * 10);
+ check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
+ i * 10 + 5);
}
}
@@ -174,7 +416,8 @@ TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
auto& driver_0 = env.get_test_icd(0);
auto& driver_1 = env.get_test_icd(1);
- std::vector<std::string> fake_function_names;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, 1);
// used to identify the GPUs
VkPhysicalDeviceProperties props{};
@@ -184,11 +427,11 @@ TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
driver_1.physical_devices.emplace_back("physical_device_1");
props.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
driver_1.physical_devices.back().set_properties(props);
- fake_function_names.push_back(std::string("vkNotIntRealFuncTEST_0"));
+ function_names.push_back(std::string("vkNotIntRealFuncTEST_0"));
custom_physical_device_functions funcs{};
- driver_0.custom_physical_device_functions.push_back(
- VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(funcs.func_zero)});
+ driver_0.physical_devices.at(0).custom_physical_device_functions.push_back(
+ VulkanFunction{function_names.back(), to_vkVoidFunction(funcs.func_zero)});
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
@@ -200,12 +443,12 @@ TEST(UnknownFunctionDeathTests, PhysicalDeviceFunctionErrorPath) {
// use the wrong GPU to query the functions, should get 5 errors
decltype(custom_physical_device_functions::func_zero)* returned_func_i =
- env.vulkan_functions.load(inst.inst, fake_function_names.at(0).c_str());
+ env.vulkan_functions.load(inst.inst, function_names.at(0).c_str());
ASSERT_NE(returned_func_i, nullptr);
ASSERT_DEATH(returned_func_i(phys_dev_to_use, 0), "Extension vkNotIntRealFuncTEST_0 not supported for this physical device");
}
-TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayer) {
+TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerImplementation) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
@@ -213,27 +456,29 @@ TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayer) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
- std::vector<std::string> fake_function_names;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
driver.physical_devices.emplace_back("physical_device_0");
- fill_custom_functions(driver.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{},
- function_count);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
"implicit_layer_unknown_function_intercept.json");
+ auto& layer = env.get_test_layer();
+ fill_implementation_functions(layer.custom_physical_device_implementation_functions, function_names,
+ layer_implementation_physical_device_functions{}, function_count);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, fake_function_names,
- function_count);
+ check_layer_custom_functions_no_interception(env.vulkan_functions, inst.inst, phys_dev, layer,
+ layer_implementation_physical_device_functions{}, function_names, function_count);
}
-TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayer) {
+TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLayerImplementation) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
@@ -242,7 +487,9 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLay
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
auto& driver_0 = env.get_test_icd(0);
auto& driver_1 = env.get_test_icd(1);
- std::vector<std::string> fake_function_names;
+ uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
// used to identify the GPUs
VkPhysicalDeviceProperties props{};
@@ -252,11 +499,11 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLay
driver_1.physical_devices.emplace_back("physical_device_1");
props.deviceType = VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU;
driver_1.physical_devices.back().set_properties(props);
- for (uint32_t i = 0; i < 25; i++) {
- fill_custom_functions(driver_0.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10);
- fill_custom_functions(driver_1.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10 + 5);
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ fill_implementation_functions(driver_0.physical_devices.at(0).custom_physical_device_functions, function_names,
+ custom_physical_device_functions{}, 5, i * 10);
+ fill_implementation_functions(driver_1.physical_devices.at(0).custom_physical_device_functions, function_names,
+ custom_physical_device_functions{}, 5, i * 10 + 5);
}
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
@@ -276,11 +523,11 @@ TEST(UnknownFunction, PhysicalDeviceFunctionMultipleDriverSupportWithImplicitLay
phys_dev_0 = phys_devs[1];
phys_dev_1 = phys_devs[0];
}
- for (uint32_t i = 0; i < 25; i++) {
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, fake_function_names,
- 5, i * 10);
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, fake_function_names,
- 5, i * 10 + 5);
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_0, custom_physical_device_functions{}, function_names, 5,
+ i * 10);
+ check_custom_functions(env.vulkan_functions, inst.inst, phys_dev_1, custom_physical_device_functions{}, function_names, 5,
+ i * 10 + 5);
}
}
@@ -292,410 +539,843 @@ TEST(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayerInterception) {
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
- std::vector<std::string> fake_function_names;
-
driver.physical_devices.emplace_back("physical_device_0");
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
+
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
.set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
"implicit_layer_unknown_function_intercept.json");
auto& layer = env.get_test_layer();
- fill_custom_functions(layer.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{},
- function_count);
+ fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, fake_function_names,
- function_count);
+ check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer,
+ layer_intercept_physical_device_functions{}, function_names, function_count);
}
-TEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception) {
+TEST(UnknownFunction, PhysicalDeviceFunctionDriverSupportWithImplicitLayerInterception) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
auto& driver = env.get_test_icd();
- std::vector<std::string> fake_function_names;
-
+ uint32_t function_count = 100;
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
driver.physical_devices.emplace_back("physical_device_0");
-
- env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
- .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept_0.json");
- auto& layer_0 = env.get_test_layer();
+ fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
+ layer_implementation_physical_device_functions{}, function_count);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept_1.json");
- auto& layer_1 = env.get_test_layer();
- for (uint32_t i = 0; i < 25; i++) {
- fill_custom_functions(layer_0.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10);
- fill_custom_functions(layer_1.custom_physical_device_functions, fake_function_names, custom_physical_device_functions{}, 5,
- i * 10 + 5);
- }
+ "implicit_layer_unknown_function_intercept.json");
+ auto& layer = env.get_test_layer();
+ fill_phys_dev_intercept_functions(layer, function_names, layer_intercept_physical_device_functions{}, function_count);
+
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
VkPhysicalDevice phys_dev = inst.GetPhysDev();
- check_custom_functions(env.vulkan_functions, inst.inst, phys_dev, custom_physical_device_functions{}, fake_function_names, 250);
+ check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer, layer_intercept_physical_device_functions{},
+ function_names, function_count);
}
-using custom_device_functions = custom_functions<VkDevice>;
-
-TEST(UnknownFunction, DeviceFunctionFromGetInstanceProcAddr) {
+TEST(UnknownFunction, PhysicalDeviceFunctionWithMultipleImplicitLayersInterception) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- std::vector<std::string> fake_function_names;
-
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_device_functions{},
- function_count);
-
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
-
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
- check_custom_functions(env.vulkan_functions, inst.inst, dev.dev, custom_device_functions{}, fake_function_names,
- function_count);
-}
-
-TEST(UnknownFunction, DeviceFunctionFromGetInstanceProcAddrWithImplicitLayer) {
-#if defined(__APPLE__)
- GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
-#endif
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
+ std::vector<std::string> function_names;
uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
- auto& driver = env.get_test_icd();
+ add_function_names(function_names, function_count);
driver.physical_devices.emplace_back("physical_device_0");
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_device_functions{},
- function_count);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
-
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
-
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
- check_custom_functions(env.vulkan_functions, inst.inst, dev.dev, custom_device_functions{}, fake_function_names,
- function_count);
-}
-
-TEST(UnknownFunction, DeviceFunctionFromGetDeviceProcAddr) {
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_device_functions{},
- function_count);
-
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
-
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
- check_custom_functions(env.vulkan_functions, dev.dev, dev.dev, custom_device_functions{}, fake_function_names, function_count);
-}
-
-TEST(UnknownFunction, DeviceFunctionFromGetDeviceProcAddrWithImplicitLayer) {
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_device_functions{},
- function_count);
+ "implicit_layer_unknown_function_intercept_0.json");
+ auto& layer_0 = env.get_test_layer(0);
+ layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
-
+ "implicit_layer_unknown_function_intercept_1.json");
+ auto& layer_1 = env.get_test_layer(1);
+ layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ fill_implementation_functions(driver.physical_devices.at(0).custom_physical_device_functions, function_names,
+ layer_implementation_physical_device_functions{}, 5, i * 10);
+ fill_phys_dev_intercept_functions(layer_0, function_names, layer_intercept_physical_device_functions{}, 5, i * 10);
+ fill_phys_dev_intercept_functions(layer_1, function_names, layer_intercept_physical_device_functions{}, 5, i * 10 + 5);
+ }
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
- check_custom_functions(env.vulkan_functions, dev.dev, dev.dev, custom_device_functions{}, fake_function_names, function_count);
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ check_layer_custom_functions(env.vulkan_functions, inst.inst, phys_dev, layer_0,
+ layer_intercept_physical_device_functions{}, function_names, 5, i * 10);
+ check_layer_custom_functions_no_implementation(env.vulkan_functions, inst.inst, phys_dev, layer_1,
+ layer_intercept_physical_device_functions{}, function_names, 5, i * 10 + 5);
+ }
}
-using custom_command_buffer_functions = custom_functions<VkCommandBuffer>;
-
-TEST(UnknownFunction, CommandBufferFunctionFromGetDeviceProcAddr) {
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
+template <typename ParentType>
+ParentType get_parent_type(InstWrapper const& inst, DeviceWrapper const& dev);
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names,
- custom_command_buffer_functions{}, function_count);
+template <>
+VkInstance get_parent_type<VkInstance>(InstWrapper const& inst, DeviceWrapper const& dev) {
+ return inst.inst;
+}
+template <>
+VkDevice get_parent_type<VkDevice>(InstWrapper const& inst, DeviceWrapper const& dev) {
+ return dev.dev;
+}
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+template <typename DispatchableHandleType>
+DispatchableHandleType get_dispatch_handle(FrameworkEnvironment& env, DeviceWrapper const& dev,
+ std::vector<TestConfig> const& flags);
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
+template <>
+VkDevice get_dispatch_handle<VkDevice>(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const& flags) {
+ return dev.dev;
+}
- DeviceFunctions funcs{env.vulkan_functions, dev};
+template <>
+VkCommandBuffer get_dispatch_handle<VkCommandBuffer>(FrameworkEnvironment& env, DeviceWrapper const& dev,
+ std::vector<TestConfig> const& flags) {
VkCommandPool command_pool;
VkCommandPoolCreateInfo pool_create_info{};
+ DeviceFunctions funcs{env.vulkan_functions, dev};
funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
VkCommandBuffer command_buffer;
VkCommandBufferAllocateInfo alloc_info{};
alloc_info.commandBufferCount = 1;
alloc_info.commandPool = command_pool;
funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
+ return command_buffer;
+}
- check_custom_functions(env.vulkan_functions, dev.dev, command_buffer, custom_command_buffer_functions{}, fake_function_names,
- function_count);
+template <>
+VkQueue get_dispatch_handle<VkQueue>(FrameworkEnvironment& env, DeviceWrapper const& dev, std::vector<TestConfig> const& flags) {
+ DeviceFunctions funcs{env.vulkan_functions, dev.dev};
+ VkQueue queue;
+ funcs.vkGetDeviceQueue(dev, 0, 0, &queue);
+ return queue;
}
-TEST(UnknownFunction, CommandBufferFunctionFromGetDeviceProcAddrWithImplicitLayer) {
+template <typename ParentType, typename DispatchableHandleType>
+void unknown_function_test_impl(std::vector<TestConfig> const& flags) {
+ using custom_functions_type = custom_functions<DispatchableHandleType>;
+ using layer_implementation_functions_type = layer_implementation_functions<DispatchableHandleType>;
+ using layer_intercept_functions_type = layer_intercept_functions<DispatchableHandleType>;
+
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
+ uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
+
auto& driver = env.get_test_icd();
driver.physical_devices.emplace_back("physical_device_0");
driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names,
- custom_command_buffer_functions{}, function_count);
- env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
- .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
+ std::vector<std::string> function_names;
+ add_function_names(function_names, function_count);
+
+ if (has_flag(flags, TestConfig::add_layer_interception)) {
+ fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
+ layer_implementation_functions_type{}, function_count);
+ } else {
+ fill_implementation_functions(driver.physical_devices.back().known_device_functions, function_names,
+ custom_functions_type{}, function_count);
+ }
+ TestLayer* layer_ptr = nullptr;
+ if (has_flag(flags, TestConfig::add_layer_implementation) || has_flag(flags, TestConfig::add_layer_interception)) {
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment("DISABLE_ME")),
+ "implicit_layer_unknown_function_intercept.json");
+ layer_ptr = &env.get_test_layer();
+ }
+ if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names,
+ layer_implementation_functions_type{}, 5, i * 10);
+ fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, 5, i * 10 + 5);
+ }
+ } else if (has_flag(flags, TestConfig::add_layer_implementation)) {
+ fill_implementation_functions(layer_ptr->custom_device_implementation_functions, function_names, custom_functions_type{},
+ function_count);
+ } else if (has_flag(flags, TestConfig::add_layer_interception)) {
+ fill_device_intercept_functions(*layer_ptr, function_names, layer_intercept_functions_type{}, function_count);
+ }
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
DeviceWrapper dev{inst};
+ dev.create_info.add_device_queue({});
dev.CheckCreate(inst.GetPhysDev());
+ auto dispatch_type = get_dispatch_handle<DispatchableHandleType>(env, dev, flags);
+ auto parent_type = get_parent_type<ParentType>(inst, dev);
+
+ if (has_flag(flags, TestConfig::add_layer_implementation) && has_flag(flags, TestConfig::add_layer_interception)) {
+ for (uint32_t i = 0; i < function_count / 10; i++) {
+ check_layer_custom_functions_no_interception(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr,
+ layer_implementation_functions_type{}, function_names, 5, i * 10);
+ }
+ } else if (has_flag(flags, TestConfig::add_layer_interception)) {
+ check_layer_custom_functions(env.vulkan_functions, parent_type, dispatch_type, *layer_ptr, layer_intercept_functions_type{},
+ function_names, function_count);
+
+ } else {
+ check_custom_functions(env.vulkan_functions, parent_type, dispatch_type, custom_functions_type{}, function_names,
+ function_count);
+ }
+}
- DeviceFunctions funcs{env.vulkan_functions, dev};
- VkCommandPool command_pool;
- VkCommandPoolCreateInfo pool_create_info{};
- funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
- VkCommandBuffer command_buffer;
- VkCommandBufferAllocateInfo alloc_info{};
- alloc_info.commandBufferCount = 1;
- alloc_info.commandPool = command_pool;
- funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
+// Device
- check_custom_functions(env.vulkan_functions, dev.dev, command_buffer, custom_command_buffer_functions{}, fake_function_names,
- function_count);
+TEST(UnknownFunction, DeviceFromGDPA) { unknown_function_test_impl<VkDevice, VkDevice>({}); }
+
+TEST(UnknownFunction, DeviceFromGDPAWithLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_implementation});
}
-TEST(UnknownFunction, CommandBufferFunctionFromGetInstanceProcAddr) {
+TEST(UnknownFunction, DeviceFromGDPAWithLayerInterception) {
+ unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception});
+}
+
+TEST(UnknownFunction, DeviceFromGDPAWithLayerInterceptionAndLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
+
+TEST(UnknownFunction, DeviceFromGIPA) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names,
- custom_command_buffer_functions{}, function_count);
+ unknown_function_test_impl<VkInstance, VkDevice>({});
+}
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+TEST(UnknownFunction, DeviceFromGIPAWithLayerImplementation) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
+}
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
+TEST(UnknownFunction, DeviceFromGIPAWithLayerInterception) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_implementation});
+}
- DeviceFunctions funcs{env.vulkan_functions, dev};
- VkCommandPool command_pool;
- VkCommandPoolCreateInfo pool_create_info{};
- funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
- VkCommandBuffer command_buffer;
- VkCommandBufferAllocateInfo alloc_info{};
- alloc_info.commandBufferCount = 1;
- alloc_info.commandPool = command_pool;
- funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
+TEST(UnknownFunction, DeviceFromGIPAWithLayerInterceptionAndLayerImplementation) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkDevice>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
- check_custom_functions(env.vulkan_functions, inst.inst, command_buffer, custom_command_buffer_functions{}, fake_function_names,
- function_count);
+// Command buffers
+
+TEST(UnknownFunction, CommandBufferFromGDPA) { unknown_function_test_impl<VkDevice, VkCommandBuffer>({}); }
+
+TEST(UnknownFunction, CommandBufferFromGDPAWithLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_implementation});
+}
+
+TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterception) {
+ unknown_function_test_impl<VkDevice, VkCommandBuffer>({TestConfig::add_layer_interception});
}
-TEST(UnknownFunction, CommandBufferFunctionFromGetInstanceProcAddrWithImplicitLayer) {
+TEST(UnknownFunction, CommandBufferFromGDPAWithLayerInterceptionAndLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkCommandBuffer>(
+ {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
+
+TEST(UnknownFunction, CommandBufferFromGIPA) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names,
- custom_command_buffer_functions{}, function_count);
+ unknown_function_test_impl<VkInstance, VkCommandBuffer>({});
+}
- env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
- .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
+TEST(UnknownFunction, CommandBufferFromGIPAWithLayerImplementation) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
+}
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterception) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkCommandBuffer>({TestConfig::add_layer_implementation});
+}
- DeviceWrapper dev{inst};
- dev.CheckCreate(inst.GetPhysDev());
+TEST(UnknownFunction, CommandBufferFromGIPAWithLayerInterceptionAndLayerImplementation) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkCommandBuffer>(
+ {TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
- DeviceFunctions funcs{env.vulkan_functions, dev};
- VkCommandPool command_pool;
- VkCommandPoolCreateInfo pool_create_info{};
- funcs.vkCreateCommandPool(dev, &pool_create_info, nullptr, &command_pool);
- VkCommandBuffer command_buffer;
- VkCommandBufferAllocateInfo alloc_info{};
- alloc_info.commandBufferCount = 1;
- alloc_info.commandPool = command_pool;
- funcs.vkAllocateCommandBuffers(dev, &alloc_info, &command_buffer);
+// Queues
- check_custom_functions(env.vulkan_functions, inst.inst, command_buffer, custom_command_buffer_functions{}, fake_function_names,
- function_count);
+TEST(UnknownFunction, QueueFromGDPA) { unknown_function_test_impl<VkDevice, VkQueue>({}); }
+
+TEST(UnknownFunction, QueueFromGDPAWithLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_implementation});
}
-using custom_queue_functions = custom_functions<VkQueue>;
+TEST(UnknownFunction, QueueFromGDPAWithLayerInterception) {
+ unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception});
+}
-TEST(UnknownFunction, QueueFunctionFromGetDeviceProcAddr) {
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_queue_functions{},
- function_count);
+TEST(UnknownFunction, QueueFromGDPAWithLayerInterceptionAndLayerImplementation) {
+ unknown_function_test_impl<VkDevice, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+TEST(UnknownFunction, QueueFromGIPA) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkQueue>({});
+}
- DeviceWrapper dev{inst};
- dev.create_info.add_device_queue({});
- dev.CheckCreate(inst.GetPhysDev());
- VkQueue queue{};
- env.vulkan_functions.vkGetDeviceQueue(dev, 0, 0, &queue);
+TEST(UnknownFunction, QueueFromGIPAWithLayer) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
+}
- check_custom_functions(env.vulkan_functions, dev.dev, queue, custom_queue_functions{}, fake_function_names, function_count);
+TEST(UnknownFunction, QueueFromGIPAWithLayerInterception) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_implementation});
}
-TEST(UnknownFunction, QueueFunctionFromGetDeviceProcAddrWithImplicitLayer) {
- FrameworkEnvironment env{};
- env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = 1000;
- auto& driver = env.get_test_icd();
- driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_queue_functions{},
- function_count);
+TEST(UnknownFunction, QueueFromGIPAWithLayerInterceptionAndLayerImplementation) {
+#if defined(__APPLE__)
+ GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+ unknown_function_test_impl<VkInstance, VkQueue>({TestConfig::add_layer_interception, TestConfig::add_layer_implementation});
+}
- env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
- .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
- .set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
+/*
+ The purpose of LayerInterceptData is to provide a place to store data that is accessible inside the interception function.
+ It works by being a templated type with static variables. Every unique type used creates a new template instantiation, with its own
+ static variable storage. Thus interception functions that are templated correctly have per-template static data storage at their
+ disposal, which is used to query the next function in the chain and call down.
+*/
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+template <typename UniqueType>
+struct LayerInterceptData {
+ static TestLayer* layer;
+ static const char* name;
+};
+template <typename UniqueType>
+TestLayer* LayerInterceptData<UniqueType>::layer = nullptr;
+template <typename UniqueType>
+const char* LayerInterceptData<UniqueType>::name = nullptr;
+
+template <typename DispatchableHandle>
+struct FunctionZero {
+ static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle handle, uint32_t a, uint32_t b) { return a + b; }
+
+ template <typename LayerType>
+ static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b) {
+ decltype(implementation)* func =
+ reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
+ if (func == nullptr) return 1337;
+ return func(handle, a + 3, b + 7);
+ }
- DeviceWrapper dev{inst};
- dev.create_info.add_device_queue({});
- dev.CheckCreate(inst.GetPhysDev());
- VkQueue queue{};
- env.vulkan_functions.vkGetDeviceQueue(dev, 0, 0, &queue);
+ template <typename ParentType>
+ static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
+ uint32_t interception_count = 1) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ EXPECT_EQ(returned_func(dispatch_type, 4, 9), (4 + 3 * interception_count) + (9 + 7 * interception_count));
+ }
+ template <typename ParentType>
+ static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
+ const char* name) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ EXPECT_EQ(returned_func(dispatch_type, 5, 2), 1337U);
+ }
+};
- check_custom_functions(env.vulkan_functions, dev.dev, queue, custom_queue_functions{}, fake_function_names, function_count);
-}
+template <typename DispatchableHandle>
+struct FunctionOne {
+ static VKAPI_ATTR uint32_t VKAPI_CALL implementation(DispatchableHandle handle, uint32_t a, uint32_t b, char c) {
+ return a + b + c;
+ }
+
+ template <typename LayerType>
+ static VKAPI_ATTR uint32_t VKAPI_CALL intercept(DispatchableHandle handle, uint32_t a, uint32_t b, char c) {
+ decltype(implementation)* func =
+ reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
+ if (func == nullptr) return 1337;
+ return func(handle, a + 2, b + 9, c + 1);
+ }
+
+ template <typename ParentType>
+ static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
+ uint32_t interception_count = 1) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ EXPECT_EQ(returned_func(dispatch_type, 12, 17, 'a'),
+ (12 + 2 * interception_count) + (17 + 9 * interception_count) + ('a' + 1 * interception_count));
+ }
+ template <typename ParentType>
+ static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
+ const char* name) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ EXPECT_EQ(returned_func(dispatch_type, 1, 516, 'c'), 1337U);
+ }
+};
+
+template <typename DispatchableHandle>
+struct FunctionTwo {
+ static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle handle, int* ptr_a, int* ptr_b) {
+ return 0.123f + *ptr_a + *ptr_b;
+ }
+
+ template <typename LayerType>
+ static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, int* ptr_b) {
+ decltype(implementation)* func =
+ reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
+ if (func == nullptr) return -1337.f;
+ *ptr_a += 2;
+ *ptr_b += 5;
+ return func(handle, ptr_a, ptr_b);
+ }
+
+ template <typename ParentType>
+ static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
+ uint32_t interception_count = 1) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ int x = 10, y = 3;
+ EXPECT_NEAR(returned_func(dispatch_type, &x, &y), 0.123f + (10 + 2 * interception_count) + (3 + 5 * interception_count),
+ 0.001);
+ }
+ template <typename ParentType>
+ static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
+ const char* name) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ int x = 10, y = 0;
+ EXPECT_NEAR(returned_func(dispatch_type, &x, &y), -1337.f, 0.001);
+ }
+};
+
+template <typename DispatchableHandle>
+struct FunctionThree {
+ static VKAPI_ATTR float VKAPI_CALL implementation(DispatchableHandle handle, int* ptr_a, float* ptr_b, uint32_t c) {
+ return 0.456f + *ptr_a + *ptr_b + c;
+ }
+
+ template <typename LayerType>
+ static VKAPI_ATTR float VKAPI_CALL intercept(DispatchableHandle handle, int* ptr_a, float* ptr_b, uint32_t c) {
+ decltype(implementation)* func =
+ reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
+ if (func == nullptr) return -1837.f;
+ *ptr_a += 55;
+ *ptr_b += 5.98f;
+ return func(handle, ptr_a, ptr_b, c + 100);
+ }
+
+ template <typename ParentType>
+ static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
+ uint32_t interception_count = 1) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ int x = 96;
+ float y = 7;
+ EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 30),
+ 0.456f + (96 + 55 * interception_count) + (7 + 5.98f * interception_count) + (30 + 100 * interception_count),
+ 0.001);
+ }
+ template <typename ParentType>
+ static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
+ const char* name) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ int x = 10;
+ float y = 0;
+ EXPECT_NEAR(returned_func(dispatch_type, &x, &y, 40), -1837.f, 0.001);
+ }
+};
+
+template <typename DispatchableHandle>
+struct FunctionFour {
+ static VKAPI_ATTR VkResult VKAPI_CALL implementation(DispatchableHandle handle, VkPhysicalDeviceLimits* limits, uint32_t* count,
+ VkExtensionProperties* props) {
+ limits->nonCoherentAtomSize = 0x0000ABCD0000FEDCU;
+ if (props == nullptr) {
+ *count = 5;
+ return VK_INCOMPLETE;
+ } else {
+ for (uint32_t i = 0; i < *count; i++) {
+ props[i].specVersion = i;
+ }
+ return VK_SUCCESS;
+ }
+ }
+
+ template <typename LayerType>
+ static VKAPI_ATTR VkResult VKAPI_CALL intercept(DispatchableHandle handle, VkPhysicalDeviceLimits* limits, uint32_t* count,
+ VkExtensionProperties* props) {
+ decltype(implementation)* func =
+ reinterpret_cast<decltype(&implementation)>(LayerType::layer->get_custom_intercept_function(LayerType::name));
+ if (func == nullptr) return VK_ERROR_DEVICE_LOST;
+ VkResult res = func(handle, limits, count, props);
+ if (props) {
+ for (uint32_t i = 5; i < *count; i++) {
+ props[i].specVersion = 1234 + i * 2;
+ }
+ } else if (count) {
+ *count += 1;
+ }
+ return res;
+ }
-TEST(UnknownFunction, QueueFunctionFromGetInstanceProcAddr) {
+ template <typename ParentType>
+ static void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type, const char* name,
+ uint32_t interception_count = 1) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ VkPhysicalDeviceLimits limits{};
+ uint32_t count = 0;
+ EXPECT_EQ(returned_func(dispatch_type, &limits, &count, nullptr), VK_INCOMPLETE);
+ EXPECT_EQ(count, 5 + interception_count);
+ std::vector<VkExtensionProperties> props(count, VkExtensionProperties{});
+ EXPECT_EQ(returned_func(dispatch_type, &limits, &count, props.data()), VK_SUCCESS);
+ for (uint32_t i = 0; i < 5; i++) {
+ EXPECT_EQ(props.at(i).specVersion, i);
+ }
+ for (uint32_t i = 5; i < interception_count; i++) {
+ EXPECT_EQ(props.at(i).specVersion, 1234 + i * 2); // interception should do this
+ }
+ }
+ template <typename ParentType>
+ static void check_no_implementation(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type,
+ const char* name) {
+ decltype(implementation)* returned_func = loader.load(parent, name);
+ ASSERT_NE(returned_func, nullptr);
+ VkPhysicalDeviceLimits limits{};
+ EXPECT_EQ(returned_func(dispatch_type, &limits, nullptr, nullptr), VK_ERROR_DEVICE_LOST);
+ }
+};
+
+struct UnknownFunction {
+ std::string name;
+
+ bool has_implementation = false;
+ std::vector<uint32_t> interception_stack;
+
+ UnknownFunction() = default;
+ UnknownFunction(std::string name) : name(name) {}
+
+ template <typename FunctionType, typename ParentType, typename DispatchableHandle>
+ void check(VulkanFunctions const& loader, ParentType parent, DispatchableHandle dispatch_type) {
+ if (has_implementation) {
+ // Find how many layers intercept this function, stop if any layer 'implements' the function, thus doesn't return
+ uint32_t intercept_count = 0;
+ for (auto const& elem : interception_stack) {
+ if (elem == 1) break;
+ intercept_count++;
+ }
+ FunctionType::Function::check(loader, parent, dispatch_type, name.c_str(), intercept_count);
+ } else {
+ FunctionType::Function::check_no_implementation(loader, parent, dispatch_type, name.c_str());
+ }
+ }
+
+ void push_layer_implementation() { interception_stack.push_back(1); }
+ void push_layer_interception() { interception_stack.push_back(0); }
+};
+
+// For VkDevice, VkCommandBuffer, & VkQueue
+template <typename FunctionType, typename DispatchableHandle>
+struct UnknownFunctionInfo {
+ using Function = FunctionType;
+
+ static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
+ physical_device.add_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
+ func.has_implementation = true;
+ }
+
+ template <typename LayerStruct>
+ static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct intercept_struct) {
+ LayerInterceptData<LayerStruct>::layer = &layer;
+ LayerInterceptData<LayerStruct>::name = func.name.c_str();
+ layer.add_custom_device_interception_function(
+ func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
+ func.push_layer_interception();
+ }
+
+ static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
+ layer.add_custom_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
+ func.has_implementation = true;
+ func.push_layer_implementation();
+ }
+};
+
+// Specialization for VkPhysicalDevice
+
+template <typename FunctionType>
+struct UnknownFunctionInfo<FunctionType, VkPhysicalDevice> {
+ using Function = FunctionType;
+
+ static void add_to_driver(UnknownFunction& func, PhysicalDevice& physical_device) {
+ physical_device.add_custom_physical_device_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
+ func.has_implementation = true;
+ }
+
+ template <typename LayerStruct>
+ static void add_to_layer(UnknownFunction& func, TestLayer& layer, LayerStruct intercept_struct) {
+ LayerInterceptData<LayerStruct>::layer = &layer;
+ LayerInterceptData<LayerStruct>::name = func.name.c_str();
+ layer.add_custom_physical_device_intercept_function(
+ func.name, to_vkVoidFunction(&Function::template intercept<LayerInterceptData<LayerStruct>>));
+ func.push_layer_interception();
+ }
+
+ static void add_implementation_to_layer(UnknownFunction& func, TestLayer& layer) {
+ layer.add_custom_physical_device_implementation_function({func.name.c_str(), to_vkVoidFunction(Function::implementation)});
+ func.has_implementation = true;
+ func.push_layer_implementation();
+ }
+};
+
+struct Functions {
+ template <template <typename> class Function>
+ struct HelperTypedef {
+ using physical_device = UnknownFunctionInfo<Function<VkPhysicalDevice>, VkPhysicalDevice>;
+ using device = UnknownFunctionInfo<Function<VkDevice>, VkDevice>;
+ using command_buffer = UnknownFunctionInfo<Function<VkCommandBuffer>, VkCommandBuffer>;
+ using queue = UnknownFunctionInfo<Function<VkQueue>, VkQueue>;
+ };
+
+ using zero = HelperTypedef<FunctionZero>;
+ using one = HelperTypedef<FunctionOne>;
+ using two = HelperTypedef<FunctionTwo>;
+ using three = HelperTypedef<FunctionThree>;
+ using four = HelperTypedef<FunctionFour>;
+};
+
+template <size_t I>
+struct D {};
+
+TEST(UnknownFunction, PhysicalDeviceFunctionTwoLayerInterception) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
+
driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_queue_functions{},
- function_count);
+ PhysicalDevice& pd = driver.physical_devices.back();
+
+ UnknownFunction f{"vkFunc1"};
+ Functions::three::physical_device::add_to_driver(f, pd);
+
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment("DISABLE_ME")),
+ "implicit_layer_unknown_function_intercept.json");
+ auto& layer0 = env.get_test_layer(0);
+ Functions::three::physical_device::add_to_layer(f, layer0, D<0>{});
+
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept2")
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment("DISABLE_ME")),
+ "implicit_layer_unknown_function_intercept2.json");
+ auto& layer1 = env.get_test_layer(1);
+
+ Functions::three::physical_device::add_to_layer(f, layer1, D<1>{});
InstWrapper inst{env.vulkan_functions};
inst.CheckCreate();
- DeviceWrapper dev{inst};
- dev.create_info.add_device_queue({});
- dev.CheckCreate(inst.GetPhysDev());
- VkQueue queue{};
- env.vulkan_functions.vkGetDeviceQueue(dev, 0, 0, &queue);
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
- check_custom_functions(env.vulkan_functions, inst.inst, queue, custom_queue_functions{}, fake_function_names, function_count);
+ f.check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
}
-TEST(UnknownFunction, QueueFunctionFromGetInstanceProcAddrWithImplicitLayer) {
+TEST(UnknownFunction, ManyCombinations) {
#if defined(__APPLE__)
GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
#endif
FrameworkEnvironment env{};
env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
- uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
auto& driver = env.get_test_icd();
+ std::vector<UnknownFunction> unknown_funcs;
+
+ unknown_funcs.emplace_back("vkZero_uint32_uint32_0");
+ unknown_funcs.emplace_back("vkOne_uint32_uint32_char_1");
+ unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_2");
+ unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_3");
+ unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_4");
+ unknown_funcs.emplace_back("vkZero_uint32_uint32_5");
+ unknown_funcs.emplace_back("vkOne_uint32_uint32_char_6");
+ unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_7");
+ unknown_funcs.emplace_back("vkThree_ptr_int_ptr_float_uint_8");
+ unknown_funcs.emplace_back("vkFour_PD_limits_ptr_uint_ptr_ExtProps_9");
+ unknown_funcs.emplace_back("vkZero_uint32_uint32_10");
+ unknown_funcs.emplace_back("vkOne_uint32_uint32_char_11");
+ unknown_funcs.emplace_back("vkTwo_ptr_int_ptr_int_12");
+
driver.physical_devices.emplace_back("physical_device_0");
- driver.physical_devices.back().add_queue_family_properties({});
- std::vector<std::string> fake_function_names;
- fill_custom_functions(driver.physical_devices.back().known_device_functions, fake_function_names, custom_queue_functions{},
- function_count);
+ PhysicalDevice& physical_device = driver.physical_devices.back();
env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
- .set_name("VK_LAYER_implicit_layer_unknown_function_intercept")
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_0")
+ .set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
+ .set_disable_environment("DISABLE_ME")
+ .add_device_extension(ManifestLayer::LayerDescription::Extension{
+ "VK_EXT_for_the_laughs", 0, {"vkOne_uint32_uint32_char_11"}})),
+ "implicit_layer_unknown_function_intercept_0.json");
+ auto& layer_0 = env.get_test_layer(0);
+ layer_0.set_use_gipa_GetPhysicalDeviceProcAddr(true);
+ env.add_implicit_layer(ManifestLayer{}.add_layer(ManifestLayer::LayerDescription{}
+ .set_name("VK_LAYER_implicit_layer_unknown_function_intercept_1")
.set_lib_path(TEST_LAYER_PATH_EXPORT_VERSION_2)
.set_disable_environment("DISABLE_ME")),
- "implicit_layer_unknown_function_intercept.json");
+ "implicit_layer_unknown_function_intercept_1.json");
+ auto& layer_1 = env.get_test_layer(1);
+ layer_1.set_use_gipa_GetPhysicalDeviceProcAddr(false);
- InstWrapper inst{env.vulkan_functions};
- inst.CheckCreate();
+ // Physical Device functions
+ Functions::zero::physical_device::add_to_driver(unknown_funcs.at(0), physical_device);
- DeviceWrapper dev{inst};
- dev.create_info.add_device_queue({});
- dev.CheckCreate(inst.GetPhysDev());
- VkQueue queue{};
- env.vulkan_functions.vkGetDeviceQueue(dev, 0, 0, &queue);
+ Functions::one::physical_device::add_to_driver(unknown_funcs.at(1), physical_device);
+ Functions::one::physical_device::add_to_layer(unknown_funcs.at(1), layer_0, D<0>{});
+
+ Functions::two::physical_device::add_to_driver(unknown_funcs.at(2), physical_device);
+ Functions::two::physical_device::add_to_layer(unknown_funcs.at(2), layer_1, D<1>{});
+
+ Functions::three::physical_device::add_to_driver(unknown_funcs.at(3), physical_device);
+ Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_0, D<2>{});
+ Functions::three::physical_device::add_to_layer(unknown_funcs.at(3), layer_1, D<3>{});
+
+ Functions::four::physical_device::add_implementation_to_layer(unknown_funcs.at(4), layer_0);
+ Functions::four::physical_device::add_to_layer(unknown_funcs.at(4), layer_1, D<4>{});
+
+ Functions::zero::physical_device::add_to_layer(unknown_funcs.at(5), layer_0, D<5>{});
+ Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(5), layer_1);
+
+ Functions::two::physical_device::add_to_driver(unknown_funcs.at(12), physical_device);
+ Functions::zero::physical_device::add_to_layer(unknown_funcs.at(12), layer_0, D<12>{});
+ Functions::zero::physical_device::add_implementation_to_layer(unknown_funcs.at(12), layer_1);
- check_custom_functions(env.vulkan_functions, inst.inst, queue, custom_queue_functions{}, fake_function_names, function_count);
+ // Device functions
+ Functions::one::device::add_to_driver(unknown_funcs.at(6), physical_device);
+
+ Functions::two::device::add_to_driver(unknown_funcs.at(7), physical_device);
+ Functions::two::device::add_to_layer(unknown_funcs.at(7), layer_0, D<6>{});
+
+ Functions::three::device::add_to_driver(unknown_funcs.at(8), physical_device);
+ Functions::three::device::add_to_layer(unknown_funcs.at(8), layer_1, D<7>{});
+
+ Functions::four::device::add_to_driver(unknown_funcs.at(9), physical_device);
+ Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_0, D<8>{});
+ Functions::four::device::add_to_layer(unknown_funcs.at(9), layer_1, D<9>{});
+
+ Functions::zero::device::add_implementation_to_layer(unknown_funcs.at(10), layer_0);
+ Functions::zero::device::add_to_layer(unknown_funcs.at(10), layer_1, D<10>{});
+
+ Functions::one::device::add_to_layer(unknown_funcs.at(11), layer_0, D<11>{});
+ Functions::one::device::add_implementation_to_layer(unknown_funcs.at(11), layer_1);
+
+ {
+ InstWrapper inst{env.vulkan_functions};
+ inst.CheckCreate();
+
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+ DeviceWrapper dev{inst};
+ dev.CheckCreate(phys_dev);
+
+ unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+
+ // Check that GIPA works for device functions
+ unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
+
+ // Check that GDPA works for device functions
+ unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
+ }
+
+ {
+ InstWrapper inst{env.vulkan_functions};
+ inst.CheckCreate();
+
+ VkPhysicalDevice phys_dev = inst.GetPhysDev();
+ DeviceWrapper dev{inst};
+ dev.CheckCreate(phys_dev);
+ // Load device functions first, to make sure order of function loading is not important
+ // Check that GIPA works for device functions
+ unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, inst.inst, dev.dev);
+ unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, inst.inst, dev.dev);
+
+ // Check that GDPA works for device functions
+ unknown_funcs.at(6).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(7).check<Functions::two::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(8).check<Functions::three::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(9).check<Functions::four::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(10).check<Functions::zero::device>(env.vulkan_functions, dev.dev, dev.dev);
+ unknown_funcs.at(11).check<Functions::one::device>(env.vulkan_functions, dev.dev, dev.dev);
+
+ unknown_funcs.at(0).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(1).check<Functions::one::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(2).check<Functions::two::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(3).check<Functions::three::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(4).check<Functions::four::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ unknown_funcs.at(5).check<Functions::zero::physical_device>(env.vulkan_functions, inst.inst, phys_dev);
+ }
}
diff --git a/tests/loader_version_tests.cpp b/tests/loader_version_tests.cpp
index 17e11092c..d621c24d6 100644
--- a/tests/loader_version_tests.cpp
+++ b/tests/loader_version_tests.cpp
@@ -595,44 +595,43 @@ TEST(MinorVersionUpdate, Version1_3) {
icd_phys_dev.known_device_functions.insert(
icd_phys_dev.known_device_functions.end(),
{
- VulkanFunction{"vkCmdBeginRendering", reinterpret_cast<void*>(test_vkCmdBeginRendering)},
- VulkanFunction{"vkCmdBindVertexBuffers2", reinterpret_cast<void*>(test_vkCmdBindVertexBuffers2)},
- VulkanFunction{"vkCmdBlitImage2", reinterpret_cast<void*>(test_vkCmdBlitImage2)},
- VulkanFunction{"vkCmdCopyBuffer2", reinterpret_cast<void*>(test_vkCmdCopyBuffer2)},
- VulkanFunction{"vkCmdCopyBufferToImage2", reinterpret_cast<void*>(test_vkCmdCopyBufferToImage2)},
- VulkanFunction{"vkCmdCopyImage2", reinterpret_cast<void*>(test_vkCmdCopyImage2)},
- VulkanFunction{"vkCmdCopyImageToBuffer2", reinterpret_cast<void*>(test_vkCmdCopyImageToBuffer2)},
- VulkanFunction{"vkCmdEndRendering", reinterpret_cast<void*>(test_vkCmdEndRendering)},
- VulkanFunction{"vkCmdPipelineBarrier2", reinterpret_cast<void*>(test_vkCmdPipelineBarrier2)},
- VulkanFunction{"vkCmdResetEvent2", reinterpret_cast<void*>(test_vkCmdResetEvent2)},
- VulkanFunction{"vkCmdResolveImage2", reinterpret_cast<void*>(test_vkCmdResolveImage2)},
- VulkanFunction{"vkCmdSetCullMode", reinterpret_cast<void*>(test_vkCmdSetCullMode)},
- VulkanFunction{"vkCmdSetDepthBiasEnable", reinterpret_cast<void*>(test_vkCmdSetDepthBiasEnable)},
- VulkanFunction{"vkCmdSetDepthBoundsTestEnable", reinterpret_cast<void*>(test_vkCmdSetDepthBoundsTestEnable)},
- VulkanFunction{"vkCmdSetDepthCompareOp", reinterpret_cast<void*>(test_vkCmdSetDepthCompareOp)},
- VulkanFunction{"vkCmdSetDepthTestEnable", reinterpret_cast<void*>(test_vkCmdSetDepthTestEnable)},
- VulkanFunction{"vkCmdSetDepthWriteEnable", reinterpret_cast<void*>(test_vkCmdSetDepthWriteEnable)},
- VulkanFunction{"vkCmdSetEvent2", reinterpret_cast<void*>(test_vkCmdSetEvent2)},
- VulkanFunction{"vkCmdSetFrontFace", reinterpret_cast<void*>(test_vkCmdSetFrontFace)},
- VulkanFunction{"vkCmdSetPrimitiveRestartEnable", reinterpret_cast<void*>(test_vkCmdSetPrimitiveRestartEnable)},
- VulkanFunction{"vkCmdSetPrimitiveTopology", reinterpret_cast<void*>(test_vkCmdSetPrimitiveTopology)},
- VulkanFunction{"vkCmdSetRasterizerDiscardEnable", reinterpret_cast<void*>(test_vkCmdSetRasterizerDiscardEnable)},
- VulkanFunction{"vkCmdSetScissorWithCount", reinterpret_cast<void*>(test_vkCmdSetScissorWithCount)},
- VulkanFunction{"vkCmdSetStencilOp", reinterpret_cast<void*>(test_vkCmdSetStencilOp)},
- VulkanFunction{"vkCmdSetStencilTestEnable", reinterpret_cast<void*>(test_vkCmdSetStencilTestEnable)},
- VulkanFunction{"vkCmdSetViewportWithCount", reinterpret_cast<void*>(test_vkCmdSetViewportWithCount)},
- VulkanFunction{"vkCmdWaitEvents2", reinterpret_cast<void*>(test_vkCmdWaitEvents2)},
- VulkanFunction{"vkCmdWriteTimestamp2", reinterpret_cast<void*>(test_vkCmdWriteTimestamp2)},
- VulkanFunction{"vkCreatePrivateDataSlot", reinterpret_cast<void*>(test_vkCreatePrivateDataSlot)},
- VulkanFunction{"vkDestroyPrivateDataSlot", reinterpret_cast<void*>(test_vkDestroyPrivateDataSlot)},
- VulkanFunction{"vkGetDeviceBufferMemoryRequirements",
- reinterpret_cast<void*>(test_vkGetDeviceBufferMemoryRequirements)},
- VulkanFunction{"vkGetDeviceImageMemoryRequirements", reinterpret_cast<void*>(test_vkGetDeviceImageMemoryRequirements)},
+ VulkanFunction{"vkCmdBeginRendering", to_vkVoidFunction(test_vkCmdBeginRendering)},
+ VulkanFunction{"vkCmdBindVertexBuffers2", to_vkVoidFunction(test_vkCmdBindVertexBuffers2)},
+ VulkanFunction{"vkCmdBlitImage2", to_vkVoidFunction(test_vkCmdBlitImage2)},
+ VulkanFunction{"vkCmdCopyBuffer2", to_vkVoidFunction(test_vkCmdCopyBuffer2)},
+ VulkanFunction{"vkCmdCopyBufferToImage2", to_vkVoidFunction(test_vkCmdCopyBufferToImage2)},
+ VulkanFunction{"vkCmdCopyImage2", to_vkVoidFunction(test_vkCmdCopyImage2)},
+ VulkanFunction{"vkCmdCopyImageToBuffer2", to_vkVoidFunction(test_vkCmdCopyImageToBuffer2)},
+ VulkanFunction{"vkCmdEndRendering", to_vkVoidFunction(test_vkCmdEndRendering)},
+ VulkanFunction{"vkCmdPipelineBarrier2", to_vkVoidFunction(test_vkCmdPipelineBarrier2)},
+ VulkanFunction{"vkCmdResetEvent2", to_vkVoidFunction(test_vkCmdResetEvent2)},
+ VulkanFunction{"vkCmdResolveImage2", to_vkVoidFunction(test_vkCmdResolveImage2)},
+ VulkanFunction{"vkCmdSetCullMode", to_vkVoidFunction(test_vkCmdSetCullMode)},
+ VulkanFunction{"vkCmdSetDepthBiasEnable", to_vkVoidFunction(test_vkCmdSetDepthBiasEnable)},
+ VulkanFunction{"vkCmdSetDepthBoundsTestEnable", to_vkVoidFunction(test_vkCmdSetDepthBoundsTestEnable)},
+ VulkanFunction{"vkCmdSetDepthCompareOp", to_vkVoidFunction(test_vkCmdSetDepthCompareOp)},
+ VulkanFunction{"vkCmdSetDepthTestEnable", to_vkVoidFunction(test_vkCmdSetDepthTestEnable)},
+ VulkanFunction{"vkCmdSetDepthWriteEnable", to_vkVoidFunction(test_vkCmdSetDepthWriteEnable)},
+ VulkanFunction{"vkCmdSetEvent2", to_vkVoidFunction(test_vkCmdSetEvent2)},
+ VulkanFunction{"vkCmdSetFrontFace", to_vkVoidFunction(test_vkCmdSetFrontFace)},
+ VulkanFunction{"vkCmdSetPrimitiveRestartEnable", to_vkVoidFunction(test_vkCmdSetPrimitiveRestartEnable)},
+ VulkanFunction{"vkCmdSetPrimitiveTopology", to_vkVoidFunction(test_vkCmdSetPrimitiveTopology)},
+ VulkanFunction{"vkCmdSetRasterizerDiscardEnable", to_vkVoidFunction(test_vkCmdSetRasterizerDiscardEnable)},
+ VulkanFunction{"vkCmdSetScissorWithCount", to_vkVoidFunction(test_vkCmdSetScissorWithCount)},
+ VulkanFunction{"vkCmdSetStencilOp", to_vkVoidFunction(test_vkCmdSetStencilOp)},
+ VulkanFunction{"vkCmdSetStencilTestEnable", to_vkVoidFunction(test_vkCmdSetStencilTestEnable)},
+ VulkanFunction{"vkCmdSetViewportWithCount", to_vkVoidFunction(test_vkCmdSetViewportWithCount)},
+ VulkanFunction{"vkCmdWaitEvents2", to_vkVoidFunction(test_vkCmdWaitEvents2)},
+ VulkanFunction{"vkCmdWriteTimestamp2", to_vkVoidFunction(test_vkCmdWriteTimestamp2)},
+ VulkanFunction{"vkCreatePrivateDataSlot", to_vkVoidFunction(test_vkCreatePrivateDataSlot)},
+ VulkanFunction{"vkDestroyPrivateDataSlot", to_vkVoidFunction(test_vkDestroyPrivateDataSlot)},
+ VulkanFunction{"vkGetDeviceBufferMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceBufferMemoryRequirements)},
+ VulkanFunction{"vkGetDeviceImageMemoryRequirements", to_vkVoidFunction(test_vkGetDeviceImageMemoryRequirements)},
VulkanFunction{"vkGetDeviceImageSparseMemoryRequirements",
- reinterpret_cast<void*>(test_vkGetDeviceImageSparseMemoryRequirements)},
- VulkanFunction{"vkGetPrivateData", reinterpret_cast<void*>(test_vkGetPrivateData)},
- VulkanFunction{"vkQueueSubmit2", reinterpret_cast<void*>(test_vkQueueSubmit2)},
- VulkanFunction{"vkSetPrivateData", reinterpret_cast<void*>(test_vkSetPrivateData)},
+ to_vkVoidFunction(test_vkGetDeviceImageSparseMemoryRequirements)},
+ VulkanFunction{"vkGetPrivateData", to_vkVoidFunction(test_vkGetPrivateData)},
+ VulkanFunction{"vkQueueSubmit2", to_vkVoidFunction(test_vkQueueSubmit2)},
+ VulkanFunction{"vkSetPrivateData", to_vkVoidFunction(test_vkSetPrivateData)},
});
icd_phys_dev.extensions.push_back({"VK_SOME_EXT_haha"});
InstWrapper inst{env.vulkan_functions};