#pragma once #include "SDL_video.h" #include "SDL_events.h" #include #include #include #include const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; #ifdef NDEBUG const bool enableValidationLayers = false; #else const bool enableValidationLayers = true; #endif VkResult CreateDebugUtilsMessengerEXT(VkInstance, const VkDebugUtilsMessengerCreateInfoEXT*, const VkAllocationCallbacks*, VkDebugUtilsMessengerEXT*); void DestroyDebugUtilsMessengerEXT(VkInstance, VkDebugUtilsMessengerEXT, const VkAllocationCallbacks*); struct QueueFamilyIndices { std::optional graphicsFamily; std::optional presentFamily; bool complete() { return graphicsFamily.has_value() && presentFamily.has_value(); } }; struct SwapChainSupportDetails { VkSurfaceCapabilitiesKHR capabilities; std::vector formats; std::vector presentModes; }; class VulkanApp { public: VulkanApp(const uint32_t& _w, const uint32_t& _h) : mWidth(_w), mHeight(_h), mWin(nullptr), mActive(false) {} void init(); void loop(); void cleanup(); private: // SDL2 SDL_Window *mWin; SDL_Event mEvent; // Not tied to library const uint32_t mWidth; const uint32_t mHeight; bool mActive; // Vulkan VkInstance mInstance; VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE; VkDevice mLogicalDevice; VkSurfaceKHR mSurface; VkSwapchainKHR mSwapChain; std::vector mSwapChainImages; std::vector mSwapChainImageViews; VkFormat mSwapChainImageFormat; VkExtent2D mSwapChainExtent; std::vector mSwapChainFramebuffers; VkRenderPass mRenderPass; VkPipelineLayout mPipelineLayout; VkPipeline mGraphicsPipeline; VkCommandPool mCommandPool; VkCommandBuffer mCommandBuffer; VkQueue mGraphicsQueue; VkQueue mPresentQueue; VkSemaphore mImageAvailableSemaphore; VkSemaphore mRenderFinishedSemaphore; VkFence mInFlightFence; VkDebugUtilsMessengerEXT mDebugMessenger; void createInstance(); void selectPhysicalDevice(); void createLogicalDevice(); void createSwapChain(); void createImageViews(); void createRenderPass(); void createGraphicsPipeline(); void createFramebuffers(); void createCommandPool(); void createCommandBuffer(); void createSyncObjects(); void recordCommandBuffer(VkCommandBuffer, uint32_t); void drawFrame(); QueueFamilyIndices findQueueFamilies(VkPhysicalDevice); bool isDeviceSuitable(VkPhysicalDevice); bool checkDeviceExtensionSupport(VkPhysicalDevice); VkShaderModule createShaderModule(const std::vector&); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice); VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector&); VkPresentModeKHR chooseSwapPresentMode(const std::vector&); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR&); // Validation layer stuff void setupDebugMessenger(); bool checkValidationLayerSupport(); static VKAPI_ATTR VkBool32 VKAPI_CALL debugCallback(VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageType, const VkDebugUtilsMessengerCallbackDataEXT* pCallbackData, void* pUserData) { fprintf(stderr, "Validation Layer: %s \n", pCallbackData->pMessage); return VK_FALSE; } };