// // Created by timo on 03.04.25. // #ifndef VULKAN_APP_H #define VULKAN_APP_H #define GLFW_INCLUDE_VULKAN #include #define GLM_FORCE_RADIANS #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace vapp{ // Change here for other presentMode const VkPresentModeKHR WISHED_PRESENT_MODE = VK_PRESENT_MODE_MAILBOX_KHR; struct Vertex{ glm::vec2 pos; glm::vec3 color; static VkVertexInputBindingDescription getBindingDescription(){ VkVertexInputBindingDescription bindingDescription{}; bindingDescription.binding = 0; bindingDescription.stride = sizeof(Vertex); bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; return bindingDescription; } static std::array getAttributeDescriptions(){ std::array attributeDescriptions{}; attributeDescriptions[0].binding = 0; attributeDescriptions[0].location = 0; attributeDescriptions[0].format = VK_FORMAT_R32G32_SFLOAT; attributeDescriptions[0].offset = offsetof(Vertex, pos); attributeDescriptions[1].binding = 0; attributeDescriptions[1].location = 1; attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; attributeDescriptions[1].offset = offsetof(Vertex, color); return attributeDescriptions; } }; // TODO: Remove const std::vector vertices = { {{-0.5f, -0.5f}, {0.0f, 1.0f, 0.0f}}, {{0.5f, -0.5f}, {0.0f, 0.0f, 1.0f}}, {{0.5f, 0.5f}, {0.0f, 1.0f, 0.0f}}, {{-0.5f, 0.5f}, {1.0f, 0.0f, 0.0f}} }; // uint16_t also possible -> change in vkCmdBindIndexBuffer also const std::vector indices = { 0, 1, 2, 2, 3, 0 }; // END Remove struct UniformBufferObject{ glm::mat4 model; glm::mat4 view; glm::mat4 proj; }; struct QueueFamilyIndices{ std::optional graphicsFamily; std::optional presentFamily; bool isComplete(){ return graphicsFamily.has_value(); } }; struct SwapChainSupportDetails{ VkSurfaceCapabilitiesKHR capabilities; std::vector formats; std::vector presentModes; }; static std::vector readFile(const std::string& filename); static std::array getAttributeDescription(); class Vulkan{ private: #pragma region Fields GLFWwindow *window; uint32_t _width, _height; 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; VkRenderPass renderPass; VkDescriptorSetLayout descriptorSetLayout; VkPipelineLayout pipelineLayout; VkPipeline graphicsPipeline; VkCommandPool commandPool; std::vector commandBuffers; std::vector imageAvailableSemaphores, renderFinishedSemaphores; std::vector inFlightFences; std::vector swapChainFramebuffers; const int MAX_FRAMES_IN_FLIGHT = 2; uint32_t currentFrame = 0; VkBuffer vertexBuffer; VkDeviceMemory vertexBufferMemory; VkBuffer indexBuffer; VkDeviceMemory indexBufferMemory; std::vector uniformBuffers; std::vector uniformBuffersMemory; std::vector uniformBuffersMapped; VkDescriptorPool descriptorPool; std::vector descriptorSets; #pragma endregion bool checkValidationLayerSupport(); std::vector getRequiredExtensions(); void createInstance(); void setupDebugMessenger(); void pickPhysicalDevice(); void createLogicalDevice(); QueueFamilyIndices findQueueFamilies(VkPhysicalDevice device); bool checkDeviceExtensionSupport(VkPhysicalDevice device); bool isDeviceSuitable(VkPhysicalDevice device); void createSurface(); SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice device); VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector& availableFormats); VkPresentModeKHR chooseSwapPresentMode(const std::vector availablePresentModes); VkExtent2D chooseSwapExtent(const VkSurfaceCapabilitiesKHR& capabilities); void createSwapChain(); void createImageViews(); void createDescriptorSetLayout(); void createGraphicsPipeline(); VkShaderModule createShaderModule(const std::vector& code); void createRenderPass(); void createFrameBuffers(); void createCommandPool(); uint32_t findMemoryType(uint32_t typeFilter, VkMemoryPropertyFlags properties); void createBuffer(VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags properties, VkBuffer &buffer, VkDeviceMemory &bufferMemory); void copyBuffer(VkBuffer srcBuffer, VkBuffer dstBuffer, VkDeviceSize size); void createVertexBuffer(); void createIndexBuffer(); void createUniformBuffers(); void createDescriptorPool(); void createDescriptorSets(); void createCommandBuffers(); void recordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex); void createSyncObjects(); void updateUniformBuffer(uint32_t currentFrame); void drawFrame(); void cleanupSwapChain(); void recreateSwapChain(); void initWindow(const char *windowName); void initVulkan(); void mainLoop(); void cleanup(); public: #ifdef DEBUG const bool enableValidationLayers = true; #else const bool enableValidationLayers = false; #endif bool framebufferResized = false; void run(const char *windowName, const uint32_t width = 800, const uint32_t height = 600); }; } // vapp #endif //VULKAN_APP_H