#define TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES 0
#endif
-// expose vk_icdNegotiateLoaderICDInterfaceVersion, vk_icdEnumerateAdapterPhysicalDevices, and vk_icdGetPhysicalDeviceProcAddr
-// through vk_icdGetInstanceProcAddr or vkGetInstanceProcAddr
-#if !defined(TEST_ICD_EXPOSE_VERSION_7)
-#define TEST_ICD_EXPOSE_VERSION_7 0
+// export vk_icdNegotiateLoaderICDInterfaceVersion, vk_icdEnumerateAdapterPhysicalDevices, and vk_icdGetPhysicalDeviceProcAddr
+// through dlsym/GetProcAddress
+// Default is *on*
+#if !defined(TEST_ICD_EXPORT_VERSION_7)
+#define TEST_ICD_EXPORT_VERSION_7 1
#endif
TestICD icd;
// Remove it from the list
icd.messenger_handles.erase(found_iter);
// Delete the handle
- delete (uint8_t*)fake_msgr_handle;
+ delete (uint8_t*)(fake_msgr_handle);
} else {
std::cerr << "Messenger not found during destroy!\n";
abort();
return VK_SUCCESS;
}
-// Forward declarations for trampolines
-extern "C" {
-#if TEST_ICD_EXPOSE_VERSION_7
-FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion);
-#if TEST_ICD_EXPORT_ICD_GPDPA
-FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName);
-#endif
-#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
-FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
- uint32_t* pPhysicalDeviceCount,
- VkPhysicalDevice* pPhysicalDevices);
-#endif
-#endif
-}
-
//// trampolines
PFN_vkVoidFunction get_instance_func_ver_1_1([[maybe_unused]] VkInstance instance, const char* pName) {
PFN_vkVoidFunction base_get_instance_proc_addr(VkInstance instance, const char* pName) {
if (pName == nullptr) return nullptr;
if (instance == NULL) {
-#if TEST_ICD_EXPOSE_VERSION_7
if (string_eq(pName, "vk_icdNegotiateLoaderICDInterfaceVersion"))
return icd.exposes_vk_icdNegotiateLoaderICDInterfaceVersion
- ? to_vkVoidFunction(vk_icdNegotiateLoaderICDInterfaceVersion)
+ ? to_vkVoidFunction(test_vk_icdNegotiateLoaderICDInterfaceVersion)
: NULL;
-#if TEST_ICD_EXPORT_ICD_GPDPA
+
if (string_eq(pName, "vk_icdGetPhysicalDeviceProcAddr"))
- return icd.exposes_vk_icdGetPhysicalDeviceProcAddr ? to_vkVoidFunction(vk_icdGetPhysicalDeviceProcAddr) : NULL;
-#endif
-#if defined(WIN32) && TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
+ return icd.exposes_vk_icdGetPhysicalDeviceProcAddr ? to_vkVoidFunction(get_physical_device_func) : NULL;
+#if defined(WIN32)
if (string_eq(pName, "vk_icdEnumerateAdapterPhysicalDevices"))
- return icd.exposes_vk_icdEnumerateAdapterPhysicalDevices ? to_vkVoidFunction(vk_icdEnumerateAdapterPhysicalDevices)
+ return icd.exposes_vk_icdEnumerateAdapterPhysicalDevices ? to_vkVoidFunction(test_vk_icdEnumerateAdapterPhysicalDevices)
: NULL;
#endif // defined(WIN32)
-#endif // TEST_ICD_EXPOSE_VERSION_7
if (string_eq(pName, "vkGetInstanceProcAddr")) return to_vkVoidFunction(test_vkGetInstanceProcAddr);
if (string_eq(pName, "vkEnumerateInstanceExtensionProperties"))
// Exported functions
extern "C" {
-#if TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
+#if TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION && TEST_ICD_EXPORT_VERSION_7
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdNegotiateLoaderICDInterfaceVersion(uint32_t* pSupportedVersion) {
return test_vk_icdNegotiateLoaderICDInterfaceVersion(pSupportedVersion);
}
#endif // TEST_ICD_EXPORT_NEGOTIATE_INTERFACE_VERSION
-#if TEST_ICD_EXPORT_ICD_GPDPA
+#if TEST_ICD_EXPORT_ICD_GPDPA && TEST_ICD_EXPORT_VERSION_7
FRAMEWORK_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetPhysicalDeviceProcAddr(VkInstance instance, const char* pName) {
return get_physical_device_func(instance, pName);
}
}
#endif // TEST_ICD_EXPORT_ICD_GIPA
-#if TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES
+#if TEST_ICD_EXPORT_ICD_ENUMERATE_ADAPTER_PHYSICAL_DEVICES && TEST_ICD_EXPORT_VERSION_7
#if defined(WIN32)
FRAMEWORK_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vk_icdEnumerateAdapterPhysicalDevices(VkInstance instance, LUID adapterLUID,
uint32_t* pPhysicalDeviceCount,
PFN_vkGetDeviceProcAddr vkGetDeviceProcAddr = nullptr;
PFN_vkCreateDevice vkCreateDevice = nullptr;
- PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
- PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
// WSI
PFN_vkCreateHeadlessSurfaceEXT vkCreateHeadlessSurfaceEXT = nullptr;
#endif // VK_USE_PLATFORM_WIN32_KHR
PFN_vkDestroySurfaceKHR vkDestroySurfaceKHR = nullptr;
+ // instance extensions functions (can only be loaded with a valid instance)
+ PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr; // Null unless the extension is enabled
+ PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr; // Null unless the extension is enabled
+ PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = nullptr; // Null unless the extension is enabled
+ PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT = nullptr; // Null unless the extension is enabled
+
// device functions
PFN_vkDestroyDevice vkDestroyDevice = nullptr;
PFN_vkGetDeviceQueue vkGetDeviceQueue = nullptr;
VulkanFunctions();
+ void load_instance_functions(VkInstance instance);
+
FromVoidStarFunc load(VkInstance inst, const char* func_name) const {
return FromVoidStarFunc(vkGetInstanceProcAddr(inst, func_name));
}
DeviceCreateInfo create_info{};
};
+template <typename HandleType, typename ParentType, typename DestroyFuncType>
+struct WrappedHandle {
+ WrappedHandle(HandleType in_handle, ParentType in_parent, DestroyFuncType in_destroy_func,
+ VkAllocationCallbacks* in_callbacks = nullptr)
+ : handle(in_handle), parent(in_parent), destroy_func(in_destroy_func), callbacks(in_callbacks) {}
+ ~WrappedHandle() {
+ if (handle) {
+ destroy_func(parent, handle, callbacks);
+ handle = VK_NULL_HANDLE;
+ }
+ }
+ WrappedHandle(WrappedHandle const&) = delete;
+ WrappedHandle& operator=(WrappedHandle const&) = delete;
+ WrappedHandle(WrappedHandle&& other) noexcept
+ : handle(other.handle), parent(other.parent), destroy_func(other.destroy_func), callbacks(other.callbacks) {
+ other.handle = VK_NULL_HANDLE;
+ }
+ WrappedHandle& operator=(WrappedHandle&& other) noexcept {
+ if (handle != VK_NULL_HANDLE) {
+ destroy_func(parent, handle, callbacks);
+ }
+ handle = other.handle;
+ other.handle = VK_NULL_HANDLE;
+ parent = other.parent;
+ destroy_func = other.destroy_func;
+ callbacks = other.callbacks;
+ return *this;
+ }
+
+ HandleType handle = VK_NULL_HANDLE;
+ ParentType parent = VK_NULL_HANDLE;
+ DestroyFuncType destroy_func = nullptr;
+ VkAllocationCallbacks* callbacks = nullptr;
+};
+
struct DebugUtilsLogger {
static VkBool32 VKAPI_PTR
DebugUtilsMessengerLoggerCallback([[maybe_unused]] VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
DebugUtilsLogger& operator=(DebugUtilsLogger&&) = delete;
// Find a string in the log output
bool find(std::string const& search_text) const { return returned_output.find(search_text) != std::string::npos; }
+ // Find the number of times a string appears in the log output
+ uint32_t count(std::string const& search_text) const {
+ uint32_t occurrences = 0;
+ std::string::size_type position = 0;
+ while ((position = returned_output.find(search_text, position)) != std::string::npos) {
+ ++occurrences;
+ position += search_text.length();
+ }
+ return occurrences;
+ }
// Look through the event log. If you find a line containing the prefix we're interested in, look for the end of
// line character, and then see if the postfix occurs in it as well.
VkDebugUtilsMessageSeverityFlagsEXT severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT,
VkAllocationCallbacks* callbacks = nullptr)
- : logger(severity), inst(inst_wrapper.inst), callbacks(callbacks) {
- vkCreateDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkCreateDebugUtilsMessengerEXT>(
- inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkCreateDebugUtilsMessengerEXT"));
- vkDestroyDebugUtilsMessengerEXT = reinterpret_cast<PFN_vkDestroyDebugUtilsMessengerEXT>(
- inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkDestroyDebugUtilsMessengerEXT"));
- };
+ : logger(severity),
+ inst(inst_wrapper.inst),
+ callbacks(callbacks),
+ local_vkCreateDebugUtilsMessengerEXT(
+ FromVoidStarFunc(inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkCreateDebugUtilsMessengerEXT"))),
+ local_vkDestroyDebugUtilsMessengerEXT(FromVoidStarFunc(
+ inst_wrapper.functions->vkGetInstanceProcAddr(inst_wrapper.inst, "vkDestroyDebugUtilsMessengerEXT"))){};
~DebugUtilsWrapper() noexcept {
if (messenger) {
- vkDestroyDebugUtilsMessengerEXT(inst, messenger, callbacks);
+ local_vkDestroyDebugUtilsMessengerEXT(inst, messenger, callbacks);
+ messenger = VK_NULL_HANDLE;
}
}
// Immoveable object
DebugUtilsWrapper& operator=(DebugUtilsWrapper&&) = delete;
bool find(std::string const& search_text) { return logger.find(search_text); }
+ uint32_t count(std::string const& search_text) { return logger.count(search_text); }
VkDebugUtilsMessengerCreateInfoEXT* get() noexcept { return logger.get(); }
DebugUtilsLogger logger;
VkInstance inst = VK_NULL_HANDLE;
VkAllocationCallbacks* callbacks = nullptr;
- PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT = nullptr;
- PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT = nullptr;
+ PFN_vkCreateDebugUtilsMessengerEXT local_vkCreateDebugUtilsMessengerEXT = nullptr;
+ PFN_vkDestroyDebugUtilsMessengerEXT local_vkDestroyDebugUtilsMessengerEXT = nullptr;
VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
};
VkResult create_surface(InstWrapper& inst, VkSurfaceKHR& out_surface, const char* api_selection = nullptr);
// Alternate parameter list for allocation callback tests
VkResult create_surface(VulkanFunctions* functions, VkInstance inst, VkSurfaceKHR& surface, const char* api_selection = nullptr);
+
+VkResult create_debug_callback(InstWrapper& inst, const VkDebugReportCallbackCreateInfoEXT& create_info,
+ VkDebugReportCallbackEXT& callback);
}
#endif // defined(WIN32)
-void try_create_swapchain(InstWrapper& inst, VkPhysicalDevice physical_device, DeviceWrapper& dev, VkSurfaceKHR& surface) {
+void try_create_swapchain(InstWrapper& inst, VkPhysicalDevice physical_device, DeviceWrapper& dev, VkSurfaceKHR const& surface) {
PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR = inst.load("vkGetPhysicalDeviceSurfaceSupportKHR");
PFN_vkCreateSwapchainKHR CreateSwapchainKHR = dev.load("vkCreateSwapchainKHR");
PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = dev.load("vkGetSwapchainImagesKHR");
DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
InstWrapper inst{env.vulkan_functions};
- inst.create_info.setup_WSI();
+ inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
FillDebugUtilsCreateDetails(inst.create_info, debug_log);
inst.CheckCreate();
DebugUtilsWrapper log{inst};
PFN_vkSubmitDebugUtilsMessageEXT submit_message = inst.load("vkSubmitDebugUtilsMessageEXT");
ASSERT_TRUE(submit_message != nullptr);
+ VkSurfaceKHR pre_surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
+ WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
+ pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
+
+ VkDebugReportCallbackEXT debug_callback{};
+ VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
+ ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
+ WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
+ pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
+
auto phys_devs = inst.GetPhysDevs();
- VkSurfaceKHR surface{};
- ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
+ std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
+ for (uint32_t i = 0; i < 35; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
for (const auto& phys_dev : phys_devs) {
DeviceWrapper dev{inst};
dev.create_info.add_extension("VK_KHR_swapchain");
dev.CheckCreate(phys_dev);
-
- try_create_swapchain(inst, phys_dev, dev, surface);
+ for (const auto& surface : surfaces) {
+ try_create_swapchain(inst, phys_dev, dev, surface.handle);
+ }
}
- env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
}
TEST(DriverUnloadingFromZeroPhysDevs, InMiddleOfList) {
InstWrapper inst{env.vulkan_functions};
inst.create_info.add_extension(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
- inst.create_info.setup_WSI();
+ inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
inst.CheckCreate();
DebugUtilsWrapper log{inst};
ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
+ VkSurfaceKHR pre_surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
+ WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
+ pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
+
+ VkDebugReportCallbackEXT debug_callback{};
+ VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
+ ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
+ WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
+ pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
+
auto phys_devs = inst.GetPhysDevs();
- VkSurfaceKHR surface{};
- ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
+ std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
+ for (uint32_t i = 0; i < 35; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
for (const auto& phys_dev : phys_devs) {
DeviceWrapper dev{inst};
dev.create_info.add_extension("VK_KHR_swapchain");
dev.CheckCreate(phys_dev);
-
- try_create_swapchain(inst, phys_dev, dev, surface);
+ for (const auto& surface : surfaces) {
+ try_create_swapchain(inst, phys_dev, dev, surface.handle);
+ }
}
- env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
}
TEST(DriverUnloadingFromZeroPhysDevs, AtFrontAndBack) {
DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
InstWrapper inst{env.vulkan_functions};
- inst.create_info.setup_WSI();
+ inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
FillDebugUtilsCreateDetails(inst.create_info, debug_log);
inst.CheckCreate();
+
DebugUtilsWrapper log{inst};
ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
+ VkSurfaceKHR pre_surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
+ WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
+ pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
+
+ VkDebugReportCallbackEXT debug_callback{};
+ VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
+ ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
+ WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
+ pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
+
auto phys_devs = inst.GetPhysDevs();
- VkSurfaceKHR surface{};
- ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
+ std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
+ for (uint32_t i = 0; i < 35; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
for (const auto& phys_dev : phys_devs) {
DeviceWrapper dev{inst};
dev.create_info.add_extension("VK_KHR_swapchain");
dev.CheckCreate(phys_dev);
- try_create_swapchain(inst, phys_dev, dev, surface);
+ for (const auto& surface : surfaces) {
+ try_create_swapchain(inst, phys_dev, dev, surface.handle);
+ }
}
- env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
}
-TEST(DriverUnloadingFromZeroPhysDevs, NoPhysicaldevices) {
+TEST(DriverUnloadingFromZeroPhysDevs, NoPhysicalDevices) {
FrameworkEnvironment env{};
add_empty_driver_for_unloading_testing(env);
add_empty_driver_for_unloading_testing(env);
DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
InstWrapper inst{env.vulkan_functions};
- inst.create_info.setup_WSI();
+ inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
FillDebugUtilsCreateDetails(inst.create_info, debug_log);
inst.CheckCreate();
DebugUtilsWrapper log{inst};
ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
+
+ VkSurfaceKHR pre_surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
+ WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
+ pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
+
+ VkDebugReportCallbackEXT debug_callback{};
+ VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
+ ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
+ WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
+ pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
+
// No physical devices == VK_ERROR_INITIALIZATION_FAILED
inst.GetPhysDevs(VK_ERROR_INITIALIZATION_FAILED);
- VkSurfaceKHR surface{};
- ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
+ std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
+ for (uint32_t i = 0; i < 35; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
+}
+
+TEST(DriverUnloadingFromZeroPhysDevs, HandleRecreation) {
+ FrameworkEnvironment env{};
+ add_empty_driver_for_unloading_testing(env);
+ add_driver_for_unloading_testing(env);
+ add_empty_driver_for_unloading_testing(env);
+ add_driver_for_unloading_testing(env);
+ add_empty_driver_for_unloading_testing(env);
+
+ DebugUtilsLogger debug_log{VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT};
+ InstWrapper inst{env.vulkan_functions};
+ inst.create_info.setup_WSI().add_extension("VK_EXT_debug_report");
+ FillDebugUtilsCreateDetails(inst.create_info, debug_log);
+ inst.CheckCreate();
+ DebugUtilsWrapper log{inst};
+ ASSERT_EQ(VK_SUCCESS, CreateDebugUtilsMessenger(log));
+
+ PFN_vkSubmitDebugUtilsMessageEXT submit_message = inst.load("vkSubmitDebugUtilsMessageEXT");
+ ASSERT_TRUE(submit_message != nullptr);
+
+ VkSurfaceKHR pre_surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, pre_surface));
+ WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR> pre_enum_phys_devs_surface{
+ pre_surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR};
+
+ VkDebugReportCallbackEXT debug_callback{};
+ VkDebugReportCallbackCreateInfoEXT debug_report_create_info{};
+ ASSERT_EQ(VK_SUCCESS, create_debug_callback(inst, debug_report_create_info, debug_callback));
+ WrappedHandle<VkDebugReportCallbackEXT, VkInstance, PFN_vkDestroyDebugReportCallbackEXT>
+ pre_enum_phys_devs_debug_report_callback{debug_callback, inst.inst, env.vulkan_functions.vkDestroyDebugReportCallbackEXT};
+
+ auto phys_devs = inst.GetPhysDevs();
+ std::vector<WrappedHandle<VkDebugUtilsMessengerEXT, VkInstance, PFN_vkDestroyDebugUtilsMessengerEXT>> messengers;
+ std::vector<WrappedHandle<VkSurfaceKHR, VkInstance, PFN_vkDestroySurfaceKHR>> surfaces;
+ for (uint32_t i = 0; i < 35; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
+ // Remove some elements arbitrarily - remove 15 of each
+ // Do it backwards so the indexes are 'corect'
+ for (uint32_t i = 31; i > 2; i -= 2) {
+ messengers.erase(messengers.begin() + i);
+ surfaces.erase(surfaces.begin() + i);
+ }
+ // Add in another 100
+ for (uint32_t i = 0; i < 100; i++) {
+ VkDebugUtilsMessengerEXT messenger;
+ ASSERT_EQ(VK_SUCCESS, env.vulkan_functions.vkCreateDebugUtilsMessengerEXT(inst.inst, log.get(), nullptr, &messenger));
+ messengers.emplace_back(messenger, inst.inst, env.vulkan_functions.vkDestroyDebugUtilsMessengerEXT);
+
+ VkSurfaceKHR surface{};
+ ASSERT_EQ(VK_SUCCESS, create_surface(inst, surface));
+ surfaces.emplace_back(surface, inst.inst, env.vulkan_functions.vkDestroySurfaceKHR);
+ }
+ for (const auto& phys_dev : phys_devs) {
+ DeviceWrapper dev{inst};
+ dev.create_info.add_extension("VK_KHR_swapchain");
+ dev.CheckCreate(phys_dev);
+ for (const auto& surface : surfaces) {
+ try_create_swapchain(inst, phys_dev, dev, surface.handle);
+ }
+ }
+ VkDebugUtilsMessengerCallbackDataEXT data{};
+ data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
+ data.pMessage = "I'm a test message!";
+ data.messageIdNumber = 1;
+ submit_message(inst.inst, VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT, VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT, &data);
- env.vulkan_functions.vkDestroySurfaceKHR(inst.inst, surface, nullptr);
+ ASSERT_EQ(120U + 1U, log.count(data.pMessage));
}