diff --git a/VulkanTutorial.cpp b/VulkanTutorial.cpp index dbc87db..3b6475c 100644 --- a/VulkanTutorial.cpp +++ b/VulkanTutorial.cpp @@ -1,20 +1,41 @@ // VulkanTutorial.cpp: 定义应用程序的入口点。 // - #include "VulkanTutorial.h" +const int Width = 800; +const int Height = 600; +const std::vector validationLayers = { + "VK_LAYER_KHRONOS_validation" + +}; + +#ifdef NDEBUG +const bool enableValidationLayers = false; +#else +const bool enableValidationLayers = true; +#endif // NDEBUG + +//window init GLFWwindow* HelloTriangleApplication::initWindow(int Width, int Height) { glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); - auto window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr); + window = glfwCreateWindow(Width, Height, "vulkan", nullptr, nullptr); return window; } - +// vulkan instace create void HelloTriangleApplication::createInstance() { - VkApplicationInfo appInfo = {}; + + // check validation layers + if (enableValidationLayers && ! checkValidationLayerSupport()) + { + throw std::runtime_error("validation layers requsted,but not available"); + } + + //setup appliaction info + VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Hello Triangle"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); @@ -22,43 +43,73 @@ void HelloTriangleApplication::createInstance() { appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; - VkInstanceCreateInfo createInfo = {}; + // setup createInfo + VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; + auto requiredExtensions = getRequiredExtensions(); + createInfo.enabledExtensionCount = static_cast(requiredExtensions.size()); + createInfo.ppEnabledExtensionNames = requiredExtensions.data(); + + + /* enable glfw extension in creatInfo uint32_t glfwExtentionCount = 0; const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtentionCount); - createInfo.enabledExtensionCount = glfwExtentionCount; createInfo.ppEnabledExtensionNames = glfwExtensions; - createInfo.enabledLayerCount = 0; + */ + // enable validation layer if available in createInfo + VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{}; + if (enableValidationLayers) + { + createInfo.enabledLayerCount = static_cast(validationLayers.size()); + createInfo.ppEnabledLayerNames = validationLayers.data(); + populateDebugMessengerCreateInfo(debugCreateInfo); + createInfo.pNext = (VkDebugUtilsMessengerCreateInfoEXT*) &debugCreateInfo; + } + else + { + createInfo.enabledLayerCount = 0; + + createInfo.pNext = nullptr; + } + + // throw error in creating instance if (vkCreateInstance(&createInfo, nullptr, &instance)!=VK_SUCCESS) { throw std::runtime_error("failed to create instance"); } - uint32_t extensionCount = 0; - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); - - std::vector extensions(extensionCount); - - vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); - + // show available extensions + + uint32_t availableExtensionCount = 0; + vkEnumerateInstanceExtensionProperties(nullptr, &availableExtensionCount, nullptr); + std::vector availableExtensions(availableExtensionCount); + vkEnumerateInstanceExtensionProperties(nullptr, &availableExtensionCount, availableExtensions.data()); std::cout << "available extensions :" << std::endl; - - for (const auto& extension : extensions) + for (const auto& extension : availableExtensions) { - std::cout << "\t" << extension.extensionName << " version:" << extension.specVersion << std::endl; + std::cout << "\t" << extension.extensionName << " ver:" << extension.specVersion << std::endl; } + } + + void HelloTriangleApplication::initVulkan() { + createInstance(); + + setupDebugMessenger(); + } + + void HelloTriangleApplication::mainLoop(GLFWwindow* window){ while (!glfwWindowShouldClose(window)) @@ -68,8 +119,15 @@ void HelloTriangleApplication::mainLoop(GLFWwindow* window){ } + + void HelloTriangleApplication::cleanup(GLFWwindow* window) { + if (enableValidationLayers) + { + DestroyDebugUtilsMessengerEXT(instance, debugMessenger, nullptr); + } + vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); @@ -77,12 +135,124 @@ void HelloTriangleApplication::cleanup(GLFWwindow* window) { glfwTerminate(); } +std::vector HelloTriangleApplication::getRequiredExtensions() { + uint32_t glfwExtensionCount = 0; + const char** glfwExtensions; + glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); + + std::vector extensions(glfwExtensions, glfwExtensions + glfwExtensionCount); + + if (enableValidationLayers) + { + extensions.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME); + + } + + return extensions; + +} + +VKAPI_ATTR VkBool32 VKAPI_CALL HelloTriangleApplication::debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData) +{ + std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; + + return VK_FALSE; +} + +void HelloTriangleApplication::setupDebugMessenger() +{ + if (! enableValidationLayers) + { + return; + } + + VkDebugUtilsMessengerCreateInfoEXT createInfo{}; + populateDebugMessengerCreateInfo(createInfo); + + + if (CreateDebugUtilsMessengerEXT(instance,&createInfo,nullptr,&debugMessenger)!= VK_SUCCESS) + { + throw std::runtime_error("failed to set up debug messenger in setupDebugMessenger"); + } + +} + +void HelloTriangleApplication::populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo) +{ + + createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT; + createInfo.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT; + createInfo.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT | + VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT; + createInfo.pfnUserCallback = &debugCallback; + createInfo.pUserData = nullptr; + +} + +bool HelloTriangleApplication::checkValidationLayerSupport() { + uint32_t layerCount; + vkEnumerateInstanceLayerProperties(&layerCount, nullptr); + + std::vector availableLayers(layerCount); + vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); + + // check if validationLayers can be found in availableLayers + for (const char* layerName: validationLayers) + { + bool layerFound = false; + for (const auto& layerProperties : availableLayers) { + if (strcmp(layerName,layerProperties.layerName)==0) + { + layerFound = true; + break; + } + } + if (!layerFound) + { + return false; + } + } + return true; +} + + +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDebugUtilsMessengerEXT* pDebugMessenger) +{ + auto func = (PFN_vkCreateDebugUtilsMessengerEXT) vkGetInstanceProcAddr(instance, "vkCreateDebugUtilsMessengerEXT"); + + if (func != nullptr) + { + return func(instance, pCreateInfo, pAllocator, pDebugMessenger); + + } + else + { + return VK_ERROR_EXTENSION_NOT_PRESENT; + } + +} + +void DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT debugMessenger, const VkAllocationCallbacks* pAllocator) +{ + auto func = (PFN_vkDestroyDebugUtilsMessengerEXT)vkGetInstanceProcAddr(instance, "vkDestroyDebugUtilsMessengerEXT"); + + if (func!=nullptr) + { + func(instance, debugMessenger, pAllocator); + } +} + int main() { HelloTriangleApplication app; - int Width = 800; - int Height = 600; try { @@ -95,3 +265,5 @@ int main() } return EXIT_SUCCESS; } + + diff --git a/VulkanTutorial.h b/VulkanTutorial.h index aa0e553..eb4bac2 100644 --- a/VulkanTutorial.h +++ b/VulkanTutorial.h @@ -6,18 +6,20 @@ #define GLFW_INCLUDE_VULKAN #include - +#include #include #include #include #include +VkResult CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,const VkAllocationCallbacks* pAllocator,VkDebugUtilsMessengerEXT* pDebugMessenger); + +void DestroyDebugUtilsMessengerEXT(VkInstance instance,VkDebugUtilsMessengerEXT debugMessenger,const VkAllocationCallbacks* pAllocator); + class HelloTriangleApplication { public: - - HelloTriangleApplication(); ~HelloTriangleApplication(); void run(int Width, int Height) { @@ -28,8 +30,12 @@ public: } private: + GLFWwindow* window; + VkInstance instance; + VkDebugUtilsMessengerEXT debugMessenger; + GLFWwindow* initWindow(int Width, int Height); void createInstance(); @@ -39,6 +45,21 @@ private: void mainLoop(GLFWwindow* window); void cleanup(GLFWwindow* window); + + bool checkValidationLayerSupport(); + + std::vector getRequiredExtensions(); + + static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback( + VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, + VkDebugUtilsMessageTypeFlagsEXT messageTypes, + const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, + void* pUserData); + + void setupDebugMessenger(); + + void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); + }; HelloTriangleApplication::HelloTriangleApplication()