From 15d33b4822d3be6f3c60f14db5762ab0e8208b01 Mon Sep 17 00:00:00 2001 From: Mark Young Date: Fri, 4 Feb 2022 09:00:55 -0700 Subject: [PATCH] Add DebugReport --- tests/CMakeLists.txt | 1 + tests/loader_debug_ext_tests.cpp | 489 +++++++++++++++++++++++++++++++ 2 files changed, 490 insertions(+) create mode 100644 tests/loader_debug_ext_tests.cpp diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index f5482543..403951ec 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -29,6 +29,7 @@ add_executable( loader_testing_main.cpp loader_alloc_callback_tests.cpp loader_get_proc_addr_tests.cpp + loader_debug_ext_tests.cpp loader_handle_validation_tests.cpp loader_layer_tests.cpp loader_regression_tests.cpp diff --git a/tests/loader_debug_ext_tests.cpp b/tests/loader_debug_ext_tests.cpp new file mode 100644 index 00000000..d7a7e431 --- /dev/null +++ b/tests/loader_debug_ext_tests.cpp @@ -0,0 +1,489 @@ +/* + * Copyright (c) 2022 The Khronos Group Inc. + * Copyright (c) 2022 Valve Corporation + * Copyright (c) 2022 LunarG, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and/or associated documentation files (the "Materials"), to + * deal in the Materials without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Materials, and to permit persons to whom the Materials are + * furnished to do so, subject to the following conditions: + * + * The above copyright notice(s) and this permission notice shall be included in + * all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + * + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE + * USE OR OTHER DEALINGS IN THE MATERIALS. + * + * Author: Charles Giessen + * Author: Mark Young + */ + +#include "test_environment.h" + +// +// VK_EXT_debug_report +// + +struct ExpectedDebugReportMessage { + bool any_message = false; + std::string message; + VkDebugReportObjectTypeEXT object_type; + VkDebugReportFlagBitsEXT flag; + bool found = false; +}; +static ExpectedDebugReportMessage expected_debug_report{}; + +static VkBool32 VKAPI_CALL test_DebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, + uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, + const char* pMessage, void* pUserData) { + if (objectType == expected_debug_report.object_type && 0 < (flags | expected_debug_report.flag)) { + std::string message_str = pMessage; + if (expected_debug_report.any_message || (std::string::npos != message_str.find(expected_debug_report.message))) { + expected_debug_report.found = true; + } + } + return VK_FALSE; +} + +static void CreateDebugReportEnvironment(FrameworkEnvironment& env, VkDebugReportFlagsEXT flags, + VkInstanceCreateInfo& create_info) { + for (uint32_t icd = 0; icd < 3; ++icd) { + env.add_icd(TestICDDetails(TEST_ICD_PATH_VERSION_6, VK_API_VERSION_1_0)); + env.get_test_icd(icd).physical_devices.push_back({}); + env.get_test_icd(icd).physical_devices.push_back({}); + } + + // Initialize the expected output + expected_debug_report.any_message = false; + expected_debug_report.message = ""; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT; + expected_debug_report.found = false; + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = flags; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + static std::vector enabled_extensions; + enabled_extensions.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); + create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + create_info.pNext = &debug_report_info; + create_info.enabledExtensionCount = static_cast(enabled_extensions.size()); + create_info.ppEnabledExtensionNames = enabled_extensions.data(); +} + +// Test creating and destroying report with errors, but none should occur. +TEST(DebugExtensionTests, NormalCreateDestroy) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + // Make sure we don't find any errors + expected_debug_report.any_message = true; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report (error/warning) created in vkCreateInstance with warning in vkCreateInstance +TEST(DebugExtensionTests, WarningInCreateInstance) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, create_info); + + VkApplicationInfo app_info; + app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0); + create_info.pApplicationInfo = &app_info; + + // Make sure we find the invalid variant message + expected_debug_report.message = "The API Variant specified"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_WARNING_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Should be found because we're reporting errors and warnings + ASSERT_EQ(true, expected_debug_report.found); +} + +// Test report (error) created in vkCreateInstance with warning in vkCreateInstance +TEST(DebugExtensionTests, WarningInCreateInstanceNotLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + VkApplicationInfo app_info; + app_info.apiVersion = VK_MAKE_API_VERSION(1, 1, 0, 0); + create_info.pApplicationInfo = &app_info; + + // Make sure we find the invalid variant message + expected_debug_report.message = "The API Variant specified"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_WARNING_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should NOT be found (because we only have errors reported in create) + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report (error/warning) created in vkCreateInstance with info in vkDestroyInstance +TEST(DebugExtensionTests, InfoInDestroyInstanceNotLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT, create_info); + + expected_debug_report.message = "destroying all debug report callbacks"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Should be not be found + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report (info) created in vkCreateInstance with info in vkDestroyInstance +TEST(DebugExtensionTests, InfoInDestroyInstanceLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, create_info); + + expected_debug_report.message = "destroying all debug report callbacks"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should be found + ASSERT_EQ(true, expected_debug_report.found); +} + +// Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices. +// This should not be logged because we have only defined the debug report logging for vkCreateInstance +// and vkDestroyInstance. +TEST(DebugExtensionTests, ErrorInEnumDevsNotLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + // Look for the invaid count param message + expected_debug_report.message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + + ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should NOT be found (because we don't have a report callback setup outside of the create/destroy instance chain) + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with error in vkEnumeratePhysicalDevices. +// This should be logged now. +TEST(DebugExtensionTests, ErrorInEnumDevsLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + // Look for the invaid count param message + expected_debug_report.message = "VUID-vkEnumeratePhysicalDevices-pPhysicalDeviceCount-parameter"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, nullptr, nullptr), VK_ERROR_INITIALIZATION_FAILED); + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should be found + ASSERT_EQ(true, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices. +// This should not be logged because type is wrong. +TEST(DebugExtensionTests, InfoInEnumDevsNotLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + expected_debug_report.message = "Trimming device count down by application request"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + + uint32_t max_count = 5; + std::array devices; + ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE); + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should not be found (because it's info) + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with info in vkEnumeratePhysicalDevices. +// This should be logged because type is correct. +TEST(DebugExtensionTests, InfoInEnumDevLogged) { + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + expected_debug_report.message = "Trimming device count down by application request"; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + + uint32_t max_count = 5; + std::array devices; + ASSERT_EQ(env.vulkan_functions.vkEnumeratePhysicalDevices(inst, &max_count, devices.data()), VK_INCOMPLETE); + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should be found + ASSERT_EQ(true, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with a manual info message of the wrong message flag type to be logged. +TEST(DebugExtensionTests, ManualInfoMessageWrongMessageFlag) { + const char my_message[] = "This is my special message!"; + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + expected_debug_report.message = my_message; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + PFN_vkDebugReportMessageEXT log_debug_report = + reinterpret_cast(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + ASSERT_NE(nullptr, log_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + + log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(inst), 0, 0, + nullptr, my_message); + + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should not be found + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with a manual info message of the wrong object type to be logged. +TEST(DebugExtensionTests, ManualInfoMessageWrongObjectType) { + const char my_message[] = "This is my special message!"; + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + // Look for any message + expected_debug_report.any_message = true; + expected_debug_report.message = my_message; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + PFN_vkDebugReportMessageEXT log_debug_report = + reinterpret_cast(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + ASSERT_NE(nullptr, log_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + + log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)(inst), 0, 0, + nullptr, my_message); + + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should not be found + ASSERT_EQ(false, expected_debug_report.found); +} + +// Test report created outside of vkCreateInstance with a manual info message to be logged. +TEST(DebugExtensionTests, ManualInfoMessageLogged) { + const char my_message[] = "This is my special message!"; + FrameworkEnvironment env{}; + VkInstanceCreateInfo create_info{}; + CreateDebugReportEnvironment(env, VK_DEBUG_REPORT_ERROR_BIT_EXT, create_info); + + expected_debug_report.message = my_message; + expected_debug_report.object_type = VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT; + expected_debug_report.flag = VK_DEBUG_REPORT_ERROR_BIT_EXT; + + VkInstance inst = VK_NULL_HANDLE; + ASSERT_EQ(env.vulkan_functions.vkCreateInstance(&create_info, nullptr, &inst), VK_SUCCESS); + PFN_vkCreateDebugReportCallbackEXT create_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT")); + PFN_vkDestroyDebugReportCallbackEXT destroy_debug_report = reinterpret_cast( + env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT")); + PFN_vkDebugReportMessageEXT log_debug_report = + reinterpret_cast(env.vulkan_functions.vkGetInstanceProcAddr(inst, "vkDebugReportMessageEXT")); + ASSERT_NE(nullptr, create_debug_report); + ASSERT_NE(nullptr, destroy_debug_report); + ASSERT_NE(nullptr, log_debug_report); + + // Setup the debug report struct + static VkDebugReportCallbackCreateInfoEXT debug_report_info{VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT}; + debug_report_info.pNext = nullptr; + debug_report_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_INFORMATION_BIT_EXT; + debug_report_info.pfnCallback = reinterpret_cast(test_DebugReportCallback); + debug_report_info.pUserData = nullptr; + + VkDebugReportCallbackEXT callback = VK_NULL_HANDLE; + ASSERT_EQ(VK_SUCCESS, create_debug_report(inst, &debug_report_info, nullptr, &callback)); + + log_debug_report(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, (uint64_t)(inst), 0, 0, + nullptr, my_message); + + destroy_debug_report(inst, callback, nullptr); + + env.vulkan_functions.vkDestroyInstance(inst, nullptr); + + // Message should be found + ASSERT_EQ(true, expected_debug_report.found); +} + +// +// VK_EXT_debug_utils +// + +// Test creating and destroying report (no logging) + +// Test report (error/warning) created in vkCreateInstance with error in create instance (logging) + +// Test report (warning) created in vkCreateInstance with error in create instance (no logging) + +// Test report (error/warning) created in vkCreateInstance with error in destroy instance (logging) + +// Test report (warning) created in vkCreateInstance with error in destroy instance (no logging) + +// Test report (error/warning) created in vkCreateInstance with error in vkEnumeratePhysicalDevices (logging) +// (NULL == pPhysicalDeviceCount) + +// Test report (error/warning) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (no logging) +// (*pPhysicalDeviceCount < number) + +// Test report (error/warning/info) created in vkCreateInstance with info in vkEnumeratePhysicalDevices (logging) +// (*pPhysicalDeviceCount < number) + +// +// VK_EXT_debug_utils +//