#define GLFW_INCLUDE_VULKAN #include #include #include #include #include #include #include #include #include "Logger.h" const uint32_t WIDTH = 800; const uint32_t HEIGHT = 600; const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; #ifdef NDEBUG const bool enableValidationLayers = false; #else const bool enableValidationLayers = true; #endif class HelloTriangleApplication { private: static VKAPI_ATTR VkBool32 VKAPI_CALL DebugCallback( VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { std::cerr << "validation layer: " << pCallbackData->pMessage << std::endl; return VK_FALSE; } private: GLFWwindow* window; VkInstance instance; std::vector 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; } bool CheckValidationLayerSupport() { uint32_t layerCount; vkEnumerateInstanceLayerProperties(&layerCount, nullptr); std::vector availableLayers(layerCount); vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); 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 vkCreateInstance( // const VkInstanceCreateInfo* pCreateInfo, // const VkAllocationCallbacks* pAllocator, // VkInstance* instance) //{ // if (pCreateInfo == nullptr || instance == nullptr) { // log("Null pointer passed to required parameter!"); // return VK_ERROR_INITIALIZATION_FAILED; // } // return vkCreateInstance(pCreateInfo, pAllocator, instance); //} public: void Run() { InitWindow(); InitVulkan(); MainLoop(); Cleanup(); } private: void CheckExtensions(const char* requiredExtensions[], uint32_t requiredExtensionsCount) { uint32_t extensionCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); std::vector extensions(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); std::string required; std::string available; required += "Required extensions:\n"; bool found = false; for (uint32_t i = 0; i < requiredExtensionsCount; i++) { std::string requiredExtension = requiredExtensions[i]; for (const auto& extension : extensions) { found = strcmp(extension.extensionName, requiredExtensions[i]); if (found) { break; } } std::string status = found ? "FOUND" : "NOT FOUND"; required += "\t" + requiredExtension + " : " + status + "\n"; } available += "available extensions:\n"; for (const auto& extension : extensions) { std::string extensionName = extension.extensionName; available += "\t" + extensionName + "\n"; } log(INFO, required); log(INFO, available); } void CreateInstance() { log(INFO, "Creating Vulkan instance"); if (enableValidationLayers && !CheckValidationLayerSupport()) { throw std::runtime_error("validation layers requested, but not available!"); } VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Hello Triangle"; appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.pEngineName = "No Engine"; appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); appInfo.apiVersion = VK_API_VERSION_1_0; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; uint32_t glfwExtensionCount = 0; const char** glfwExtensions; glfwExtensions = glfwGetRequiredInstanceExtensions(&glfwExtensionCount); createInfo.enabledExtensionCount = glfwExtensionCount; createInfo.ppEnabledExtensionNames = glfwExtensions; if (enableValidationLayers) { createInfo.enabledLayerCount = static_cast(validationLayers.size()); createInfo.ppEnabledLayerNames = validationLayers.data(); } else { createInfo.enabledLayerCount = 0; } if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } CheckExtensions(glfwExtensions, glfwExtensionCount); auto extensions = GetRequiredExtensions(); createInfo.enabledExtensionCount = static_cast(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); } void InitWindow() { log(INFO, "Initializing GLFW window..."); glfwInit(); glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); glfwWindowHint(GLFW_RESIZABLE, GLFW_FALSE); window = glfwCreateWindow(WIDTH, HEIGHT, "Vulkan", nullptr, nullptr); } void InitVulkan() { log(INFO, "Initializing Vulkan..."); CreateInstance(); } void MainLoop() { while (!glfwWindowShouldClose(window)) { glfwPollEvents(); } } void Cleanup() { vkDestroyInstance(instance, nullptr); glfwDestroyWindow(window); glfwTerminate(); } }; int main() { HelloTriangleApplication app; try { app.Run(); } catch (const std::exception& e) { std::cerr << e.what() << std::endl; return EXIT_FAILURE; } return EXIT_SUCCESS; }