#ifndef HelloTriangleApplication_H_ #define HelloTriangleApplication_H_ #define GLFW_INCLUDE_VULKAN #include #define GLM_FORCE_RADIANS #define GLM_FORCE_DEPTH_ZERO_TO_ONE #include #include #include #include #include #include #include #include #include #include #include #ifdef NDEBUG const bool enableValidationLayers = false; #else const bool enableValidationLayers = true; #endif const int MAX_FRAMES_IN_FLIGHT = 2; const uint32_t WIDTH = 800; const uint32_t HEIGHT = 600; const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; struct QueueFamilyIndices { std::optional graphicsFamily; std::optional presentFamily; bool isComplete() { return graphicsFamily.has_value() && presentFamily.has_value(); } }; struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; std::vector presentModes; }; class HelloTriangleApplication { public: void run() { initWindow(); initVulkan(); mainLoop(); cleanup(); } private: GLFWwindow* window; VkInstance instance; VkDebugUtilsMessengerEXT debugMessenger; VkSurfaceKHR surface; VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; VkDevice device; VkQueue graphicsQueue; VkQueue presentQueue; VkSwapchainKHR swapChain; std::vector swapChainImages; VkFormat swapChainImageFormat; VkExtent2D swapChainExtent; std::vector swapChainImageViews; std::vector swapChainFramebuffers; VkRenderPass renderPass; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; VkCommandPool commandPool; std::vector commandBuffers; std::vector imageAvailableSemaphores; std::vector renderFinishedSemaphores; std::vector inFlightFences; std::vector imagesInFlight; size_t currentFrame = 0; bool framebufferResized = false; void initWindow(); void initVulkan(); void mainLoop(); static void framebufferResizeCallback(GLFWwindow* window, int width, int height) { auto app = reinterpret_cast(glfwGetWindowUserPointer(window)); app->framebufferResized = true; } void cleanupSwapChain(); void cleanup(); void recreateSwapChain(); void createInstance(); void populateDebugMessengerCreateInfo(VkDebugUtilsMessengerCreateInfoEXT& createInfo); void setupDebugMessenger(); void createSurface() { if (glfwCreateWindowSurface(instance, window, nullptr, &surface) != VK_SUCCESS) { throw std::runtime_error("failed to create window surface!"); } } void pickPhysicalDevice(); void createLogicalDevice(); void createSwapChain(); void createImageViews(); void createRenderPass(); void createGraphicsPipeline(); void createFramebuffers(); void createCommandPool(); void createCommandBuffers(); void createSyncObjects(); void drawFrame(); VkShaderModule createShaderModule(const std::vector& code); VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats); VkPresentModeKHR chooseSwapPresentMode(const std::vector& availablePresentModes); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); bool isDeviceSuitable(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device); QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); std::vector getRequiredExtensions(); bool checkValidationLayerSupport(); static std::vector readFile(const std::string& filename); static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData); }; #endif