#pragma once #include #include #include #include #include #include #include #include #include #include #include "vk_types.hh" const std::vector validationLayers = { "VK_LAYER_KHRONOS_validation" }; const std::vector deviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME }; const int MAX_FRAMES_IN_FLIGHT = 2; VkResult CreateDebugUtilsMessengerEXT(VkInstance, const VkDebugUtilsMessengerCreateInfoEXT*, const VkAllocationCallbacks*, VkDebugUtilsMessengerEXT*); void DestroyDebugUtilsMessengerEXT(VkInstance, VkDebugUtilsMessengerEXT, const VkAllocationCallbacks*); class VulkanApp { public: VulkanApp(const char *_t, const uint32_t& _w, const uint32_t& _h) : mWin(nullptr), mWidth(_w), mHeight(_h), mTitle(_t), mResized(false), mMinimized(false), mPhysicalDevice(nullptr) {} ~VulkanApp() { cleanup(); } SDL_AppResult mAppState = SDL_APP_CONTINUE; SDL_AppResult init(); SDL_AppResult loop(); inline bool minimized() { return mMinimized; } inline void minimized(bool _v) { mMinimized = _v; } inline void resized(bool _v) { mResized = _v; } private: // SDL3 SDL_Window *mWin; uint32_t mWidth; uint32_t mHeight; const char *mTitle; bool mResized; bool mMinimized; #ifdef NDEBUG const bool mEnableValidationLayers = false; #else const bool mEnableValidationLayers = true; #endif // Vulkan VkInstance mInstance; VkPhysicalDevice mPhysicalDevice; 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; std::vector mCommandBuffers; VkQueue mGraphicsQueue; VkQueue mPresentQueue; std::vector mImageAvailableSemaphores; std::vector mRenderFinishedSemaphores; std::vector mInFlightFences; VkDebugUtilsMessengerEXT mDebugMessenger; void createInstance(); void selectPhysicalDevice(); void createLogicalDevice(); void createSwapChain(); void recreateSwapChain(); void cleanupSwapChain(); void createImageViews(); void createRenderPass(); void createGraphicsPipeline(); void createFramebuffers(); void createCommandPool(); void createCommandBuffer(); void createSyncObjects(); void recordCommandBuffer(VkCommandBuffer, uint32_t); void drawFrame(); void cleanup(); 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) { (void)pUserData; if(messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) { SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Validation Layer [Error/Warning]: %s \n", pCallbackData->pMessage); } else if(messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) { SDL_Log("Validation Layer [General]: %s \n", pCallbackData->pMessage); } else { SDL_Log("Validation Layer: %s \n", pCallbackData->pMessage); } return VK_FALSE; } };