Expand unknown function handling tests
authorCharles Giessen <charles@lunarg.com>
Mon, 14 Feb 2022 23:03:40 +0000 (16:03 -0700)
committerCharles Giessen <46324611+charles-lunarg@users.noreply.github.com>
Tue, 15 Feb 2022 17:48:53 +0000 (10:48 -0700)
Add tests for unknown device functions queried with both vkGetDeviceProcAddr
and vkGetInstanceProcAddr. Also loops enough times to exhaust the available
unknown function supply.

Had to fix the vk_layerGetPhysicalDeviceProcAddr in TestLayer to make the tests
pass.

MacOS currently skips tests which use vkGetInstanceProcAddr. This is due to the
need for unknown functions being lower priority and so do not warrent the time
needed to write the assembly necessary to resolve the issue fully.

loader/loader.c
tests/framework/icd/physical_device.h
tests/framework/icd/test_icd.cpp
tests/framework/layer/test_layer.cpp
tests/framework/layer/test_layer.h
tests/framework/test_util.cpp
tests/framework/test_util.h
tests/loader_unknown_ext_tests.cpp

index dc7a1dde643f64e90192f52fb3121c9471c1aa1c..de74342d548c6f77e15305ad9ba7d5bf6b7a472b 100644 (file)
@@ -4271,7 +4271,7 @@ static bool loader_add_phys_dev_ext_table(struct loader_instance *inst, uint32_t
             inst->phys_dev_ext_disp_hash[i].func_name =
                 (char *)loader_instance_heap_alloc(inst, strlen(funcName) + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
             if (inst->phys_dev_ext_disp_hash[i].func_name == NULL) {
-                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_add_dev_ext_table() can't reallocate func_name memory");
+                loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "loader_add_phys_dev_ext_table() can't reallocate func_name memory");
                 return false;
             }
             strncpy(inst->phys_dev_ext_disp_hash[i].func_name, funcName, strlen(funcName) + 1);
index 243674ac518eaa79c0b89c7e74b645014cb959b8..8ee79030b8f2898e5715af6fb07cd1c729f682c7 100644 (file)
@@ -67,6 +67,8 @@ struct PhysicalDevice {
     // VkDevice handles created from this physical device
     std::vector<VkDevice> device_handles;
 
+    std::vector<DispatchableHandle<VkQueue>> queue_handles;
+
     // 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.
index 94bc7157dcd5b1aa15203593dc3a329372fbd229..389bddc63326c1727440f3ae6eaf14eb180a6059 100644 (file)
@@ -303,6 +303,11 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateDevice(VkPhysicalDevice physicalDevi
     *pDevice = device_handle.handle;
     found->device_handles.push_back(device_handle.handle);
     icd.device_handles.emplace_back(std::move(device_handle));
+
+    for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
+        found->queue_handles.emplace_back();
+    }
+
     return VK_SUCCESS;
 }
 
@@ -746,6 +751,10 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkAllocateCommandBuffers(VkDevice device, co
     return VK_SUCCESS;
 }
 
+VKAPI_ATTR void VKAPI_CALL test_vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue* pQueue) {
+    *pQueue = icd.physical_devices.back().queue_handles[queueIndex].handle;
+}
+
 // VK_EXT_acquire_drm_display
 VKAPI_ATTR VkResult VKAPI_CALL test_vkAcquireDrmDisplayEXT(VkPhysicalDevice physicalDevice, int32_t drmFd, VkDisplayKHR display) {
     return VK_SUCCESS;
@@ -1241,15 +1250,12 @@ PFN_vkVoidFunction get_instance_func(VkInstance instance, const char* pName) {
 }
 
 PFN_vkVoidFunction get_device_func(VkDevice device, const char* pName) {
-    bool found = false;
-    PhysicalDevice* found_phys_dev{};
-    for (auto& phys_dev : icd.physical_devices) {
-        for (auto& device_handle : phys_dev.device_handles) {
-            if (device_handle == device) {
-                found = true;
-                found_phys_dev = &phys_dev;
-                break;
-            }
+    if (device != nullptr) {
+        if (!std::any_of(icd.physical_devices.begin(), icd.physical_devices.end(), [&](const PhysicalDevice& pd) {
+                return std::any_of(pd.device_handles.begin(), pd.device_handles.end(),
+                                   [&](const VkDevice& pd_device) { return pd_device == device; });
+            })) {
+            return nullptr;
         }
     }
     if (string_eq(pName, "vkDestroyDevice")) return to_vkVoidFunction(test_vkDestroyDevice);
@@ -1292,6 +1298,10 @@ PFN_vkVoidFunction base_get_instance_proc_addr(VkInstance instance, const char*
 
     auto instance_func_return = get_instance_func(instance, pName);
     if (instance_func_return != nullptr) return instance_func_return;
+
+    // Need to return function pointers for device extensions
+    auto device_func_return = get_device_func(nullptr, pName);
+    if (device_func_return != nullptr) return device_func_return;
     return nullptr;
 }
 
index c3944e03fab24f006935026b4f15deb84076f7d4..37cd4e193ffd7a2a74c94933fd0f96961cfb2974 100644 (file)
@@ -146,6 +146,8 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo*
     }
 
     layer.next_vkGetInstanceProcAddr = fpGetInstanceProcAddr;
+    layer.next_GetPhysicalDeviceProcAddr =
+        reinterpret_cast<PFN_GetPhysicalDeviceProcAddr>(fpGetInstanceProcAddr(*pInstance, "vk_layerGetPhysicalDeviceProcAddr"));
 
     // Advance the link info for the next element of the chain
     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
@@ -366,7 +368,7 @@ FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDe
 #if TEST_LAYER_EXPORT_GET_PHYSICAL_DEVICE_PROC_ADDR
 FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_layerGetPhysicalDeviceProcAddr(VkInstance instance,
                                                                                             const char* pName) {
-    return nullptr;
+    return layer.next_GetPhysicalDeviceProcAddr(instance, pName);
 }
 #endif
 
index 7034dcec6501518de27d7152a4efda89518a14c0..6c421f4d8fb0c4dddcc92945523177fcd728c9b8 100644 (file)
@@ -121,6 +121,7 @@ struct TestLayer {
     BUILDER_VALUE(TestLayer, std::function<VkResult(TestLayer& layer)>, create_device_callback, {})
 
     PFN_vkGetInstanceProcAddr next_vkGetInstanceProcAddr = VK_NULL_HANDLE;
+    PFN_GetPhysicalDeviceProcAddr next_GetPhysicalDeviceProcAddr = VK_NULL_HANDLE;
     PFN_vkGetDeviceProcAddr next_vkGetDeviceProcAddr = VK_NULL_HANDLE;
 
     VkInstance instance_handle;
index e92136f6977294784e08be8dd045763b10e61b54..e5666ba18445230c1b9e4705702f3cdaef43443e 100644 (file)
@@ -645,15 +645,23 @@ InstanceCreateInfo& InstanceCreateInfo::set_api_version(uint32_t major, uint32_t
 
 DeviceQueueCreateInfo::DeviceQueueCreateInfo() { queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; }
 
+VkDeviceQueueCreateInfo DeviceQueueCreateInfo::get() noexcept {
+    queue_create_info.pQueuePriorities = priorities.data();
+    return queue_create_info;
+}
+
 VkDeviceCreateInfo* DeviceCreateInfo::get() noexcept {
     dev.enabledLayerCount = static_cast<uint32_t>(enabled_layers.size());
     dev.ppEnabledLayerNames = enabled_layers.data();
     dev.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions.size());
     dev.ppEnabledExtensionNames = enabled_extensions.data();
     uint32_t index = 0;
-    for (auto& queue : queue_infos) queue.queueFamilyIndex = index++;
+    for (auto& queue : queue_info_details) {
+        queue.queue_create_info.queueFamilyIndex = index++;
+        device_queue_infos.push_back(queue.get());
+    }
 
-    dev.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size());
-    dev.pQueueCreateInfos = queue_infos.data();
+    dev.queueCreateInfoCount = static_cast<uint32_t>(device_queue_infos.size());
+    dev.pQueueCreateInfos = device_queue_infos.data();
     return &dev;
 }
\ No newline at end of file
index 4dc0d9f106b63e4909182b9584ffb1ebe0031680..0ab83924025169b604f6d080e72c5971cd40c916 100644 (file)
@@ -783,6 +783,7 @@ struct DeviceQueueCreateInfo {
     BUILDER_VECTOR(DeviceQueueCreateInfo, float, priorities, priority)
 
     DeviceQueueCreateInfo();
+    VkDeviceQueueCreateInfo get() noexcept;
 };
 
 struct DeviceCreateInfo {
@@ -790,9 +791,11 @@ struct DeviceCreateInfo {
     BUILDER_VECTOR(DeviceCreateInfo, const char*, enabled_extensions, extension)
     BUILDER_VECTOR(DeviceCreateInfo, const char*, enabled_layers, layer)
     BUILDER_VECTOR(DeviceCreateInfo, DeviceQueueCreateInfo, queue_info_details, device_queue)
-    BUILDER_VECTOR(DeviceCreateInfo, VkDeviceQueueCreateInfo, queue_infos, queue_info)
 
     VkDeviceCreateInfo* get() noexcept;
+
+   private:
+    std::vector<VkDeviceQueueCreateInfo> device_queue_infos;
 };
 
 inline bool operator==(const VkExtent3D& a, const VkExtent3D& b) {
@@ -818,7 +821,7 @@ inline bool operator==(const VkExtensionProperties& a, const VkExtensionProperti
 inline bool operator!=(const VkExtensionProperties& a, const VkExtensionProperties& b) { return !(a == b); }
 
 struct VulkanFunction {
-    const char* name;
+    std::string name;
     void* function;
 };
 template <typename T, size_t U>
index 2c7f2b34e8859d631d7318f00d074ec28f3b2eea..c6056493fdfd0acdf22c3b0d6185da0c615520fc 100644 (file)
 
 #include "test_environment.h"
 
-class UnknownExtension : public ::testing::Test {
+class UnknownFunction : public ::testing::Test {
    protected:
     virtual void SetUp() {
         env = std::unique_ptr<FrameworkEnvironment>(new FrameworkEnvironment());
-        env->add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_2_EXPORT_ICD_GPDPA));
+        env->add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6));
     }
 
     virtual void TearDown() { env.reset(); }
@@ -44,24 +44,519 @@ class UnknownExtension : public ::testing::Test {
  function to verify that the unknown physical device function dispatching is working correctly.
 */
 
-VkResult custom_physical_device_function(VkPhysicalDevice device, int foo, int bar) { return VK_SUCCESS; }
+VKAPI_ATTR int VKAPI_CALL custom_physical_device_function(VkPhysicalDevice device, int foo, int bar) { return foo + bar; }
 using PFN_custom_physical_device_function = decltype(&custom_physical_device_function);
 
-TEST_F(UnknownExtension, ICDKnownExtension) {
+TEST_F(UnknownFunction, PhysicalDeviceFunction) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    uint32_t function_count = MAX_NUM_UNKNOWN_EXTS;
     auto& driver = env->get_test_icd();
-    const char* fake_function_name = "vkNotRealFuncTEST";
+    std::vector<std::string> fake_function_names;
 
     driver.physical_devices.emplace_back("physical_device_0");
-    driver.custom_physical_device_functions.push_back(
-        VulkanFunction{fake_function_name, reinterpret_cast<void*>(custom_physical_device_function)});
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+
+        driver.custom_physical_device_functions.push_back(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_physical_device_function)});
+    }
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    VkPhysicalDevice phys_dev = inst.GetPhysDev();
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_physical_device_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(phys_dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, PhysicalDeviceFunctionWithImplicitLayer) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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");
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+
+        driver.custom_physical_device_functions.push_back(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_physical_device_function)});
+    }
+
+    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");
 
     InstWrapper inst{env->vulkan_functions};
     inst.CheckCreate();
 
     VkPhysicalDevice phys_dev = inst.GetPhysDev();
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_physical_device_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(phys_dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+VKAPI_ATTR int VKAPI_CALL custom_device_function(VkDevice device, int foo, int bar) { return foo + bar; }
+using PFN_custom_device_function = decltype(&custom_device_function);
+
+TEST_F(UnknownFunction, DeviceFunctionFromGetInstanceProcAddr) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_device_function)});
+    }
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+    // auto createCommandPool =
+    //    reinterpret_cast<PFN_vkCreateCommandPool>(env->vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateCommandPool"));
+    // createCommandPool(dev.dev, nullptr, nullptr, nullptr);
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_device_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(dev.dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, DeviceFunctionFromGetInstanceProcAddrWithImplicitLayer) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_device_function)});
+    }
+
+    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");
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_device_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(dev.dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, DeviceFunctionFromGetDeviceProcAddr) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_device_function)});
+    }
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_device_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, DeviceFunctionFromGetDeviceProcAddrWithImplicitLayer) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_device_function)});
+    }
+
+    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");
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_device_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(dev, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+VKAPI_ATTR int VKAPI_CALL custom_command_buffer_function(VkCommandBuffer commandBuffer, int foo, int bar) { return foo + bar; }
+using PFN_custom_command_buffer_function = decltype(&custom_command_buffer_function);
+
+// command buffer
+// command buffer with implicit layer
+
+TEST_F(UnknownFunction, CommandBufferFunctionFromGetDeviceProcAddr) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_command_buffer_function)});
+    }
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_command_buffer_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(command_buffer, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, CommandBufferFunctionFromGetDeviceProcAddrWithImplicitLayer) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_command_buffer_function)});
+    }
+
+    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");
 
-    PFN_custom_physical_device_function returned_func = reinterpret_cast<PFN_custom_physical_device_function>(
-        env->vulkan_functions.vkGetInstanceProcAddr(inst.inst, fake_function_name));
-    ASSERT_NE(returned_func, nullptr);
-    ASSERT_EQ(returned_func(phys_dev, 42, 58008), VK_SUCCESS);
-}
\ No newline at end of file
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_command_buffer_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(command_buffer, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, CommandBufferFunctionFromGetInstanceProcAddr) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_command_buffer_function)});
+    }
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_command_buffer_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(command_buffer, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, CommandBufferFunctionFromGetInstanceProcAddrWithImplicitLayer) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_command_buffer_function)});
+    }
+
+    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");
+
+    InstWrapper inst{env->vulkan_functions};
+    inst.CheckCreate();
+
+    DeviceWrapper dev{inst};
+    dev.CheckCreate(inst.GetPhysDev());
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_command_buffer_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(command_buffer, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+VKAPI_ATTR int VKAPI_CALL custom_queue_function(VkQueue queue, int foo, int bar) { return foo + bar; }
+using PFN_custom_queue_function = decltype(&custom_queue_function);
+
+TEST_F(UnknownFunction, QueueFunctionFromGetDeviceProcAddr) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_queue_function)});
+    }
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_queue_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(queue, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, QueueFunctionFromGetDeviceProcAddrWithImplicitLayer) {
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_queue_function)});
+    }
+
+    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");
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_queue_function returned_func = env->vulkan_functions.load(dev.dev, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(queue, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, QueueFunctionFromGetInstanceProcAddr) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_queue_function)});
+    }
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_queue_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(queue, i, j), i + j);
+        i++;
+        j--;
+    }
+}
+
+TEST_F(UnknownFunction, QueueFunctionFromGetInstanceProcAddrWithImplicitLayer) {
+#if defined(__APPLE__)
+    GTEST_SKIP() << "Skip this test as currently macOS doesn't fully support unknown functions.";
+#endif
+    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;
+    for (uint32_t i = 0; i < function_count; i++) {
+        fake_function_names.push_back(std::string("vkNotRealFuncTEST_") + std::to_string(i));
+        driver.physical_devices.back().add_device_function(
+            VulkanFunction{fake_function_names.back(), reinterpret_cast<void*>(custom_queue_function)});
+    }
+
+    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");
+
+    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);
+
+    int i = 0, j = 1000;
+    for (const auto& function_name : fake_function_names) {
+        PFN_custom_queue_function returned_func = env->vulkan_functions.load(inst.inst, function_name.c_str());
+        ASSERT_NE(returned_func, nullptr);
+        ASSERT_EQ(returned_func(queue, i, j), i + j);
+        i++;
+        j--;
+    }
+}