From: Charles Giessen Date: Mon, 14 Feb 2022 23:03:40 +0000 (-0700) Subject: Expand unknown function handling tests X-Git-Tag: upstream/v1.3.207~26 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b53e82543ef7885c9b883cc05f97e72730b4fce4;p=platform%2Fupstream%2FVulkan-Loader.git Expand unknown function handling tests 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. --- diff --git a/loader/loader.c b/loader/loader.c index dc7a1dde..de74342d 100644 --- a/loader/loader.c +++ b/loader/loader.c @@ -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); diff --git a/tests/framework/icd/physical_device.h b/tests/framework/icd/physical_device.h index 243674ac..8ee79030 100644 --- a/tests/framework/icd/physical_device.h +++ b/tests/framework/icd/physical_device.h @@ -67,6 +67,8 @@ struct PhysicalDevice { // VkDevice handles created from this physical device std::vector device_handles; + std::vector> 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. diff --git a/tests/framework/icd/test_icd.cpp b/tests/framework/icd/test_icd.cpp index 94bc7157..389bddc6 100644 --- a/tests/framework/icd/test_icd.cpp +++ b/tests/framework/icd/test_icd.cpp @@ -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; } diff --git a/tests/framework/layer/test_layer.cpp b/tests/framework/layer/test_layer.cpp index c3944e03..37cd4e19 100644 --- a/tests/framework/layer/test_layer.cpp +++ b/tests/framework/layer/test_layer.cpp @@ -146,6 +146,8 @@ VKAPI_ATTR VkResult VKAPI_CALL test_vkCreateInstance(const VkInstanceCreateInfo* } layer.next_vkGetInstanceProcAddr = fpGetInstanceProcAddr; + layer.next_GetPhysicalDeviceProcAddr = + reinterpret_cast(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 diff --git a/tests/framework/layer/test_layer.h b/tests/framework/layer/test_layer.h index 7034dcec..6c421f4d 100644 --- a/tests/framework/layer/test_layer.h +++ b/tests/framework/layer/test_layer.h @@ -121,6 +121,7 @@ struct TestLayer { BUILDER_VALUE(TestLayer, std::function, 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; diff --git a/tests/framework/test_util.cpp b/tests/framework/test_util.cpp index e92136f6..e5666ba1 100644 --- a/tests/framework/test_util.cpp +++ b/tests/framework/test_util.cpp @@ -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(enabled_layers.size()); dev.ppEnabledLayerNames = enabled_layers.data(); dev.enabledExtensionCount = static_cast(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(queue_infos.size()); - dev.pQueueCreateInfos = queue_infos.data(); + dev.queueCreateInfoCount = static_cast(device_queue_infos.size()); + dev.pQueueCreateInfos = device_queue_infos.data(); return &dev; } \ No newline at end of file diff --git a/tests/framework/test_util.h b/tests/framework/test_util.h index 4dc0d9f1..0ab83924 100644 --- a/tests/framework/test_util.h +++ b/tests/framework/test_util.h @@ -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 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 diff --git a/tests/loader_unknown_ext_tests.cpp b/tests/loader_unknown_ext_tests.cpp index 2c7f2b34..c6056493 100644 --- a/tests/loader_unknown_ext_tests.cpp +++ b/tests/loader_unknown_ext_tests.cpp @@ -27,11 +27,11 @@ #include "test_environment.h" -class UnknownExtension : public ::testing::Test { +class UnknownFunction : public ::testing::Test { protected: virtual void SetUp() { env = std::unique_ptr(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 fake_function_names; driver.physical_devices.emplace_back("physical_device_0"); - driver.custom_physical_device_functions.push_back( - VulkanFunction{fake_function_name, reinterpret_cast(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(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 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(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 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(custom_device_function)}); + } + + InstWrapper inst{env->vulkan_functions}; + inst.CheckCreate(); + + DeviceWrapper dev{inst}; + dev.CheckCreate(inst.GetPhysDev()); + // auto createCommandPool = + // reinterpret_cast(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 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(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 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(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 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(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 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(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 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(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( - 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 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(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 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(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 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(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 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(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 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(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 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(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--; + } +}