VulkanSDL3/include/vk_app.hh
2025-08-08 13:42:13 -04:00

138 lines
4.3 KiB
C++

#pragma once
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_vulkan.h>
#include <vulkan/vulkan.h>
#include <stdexcept>
#include <set>
#include <limits>
#include <algorithm>
#include <vector>
#include <optional>
#include "vk_types.hh"
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
};
const std::vector<const char*> 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<VkImage> mSwapChainImages;
std::vector<VkImageView> mSwapChainImageViews;
VkFormat mSwapChainImageFormat;
VkExtent2D mSwapChainExtent;
std::vector<VkFramebuffer> mSwapChainFramebuffers;
VkRenderPass mRenderPass;
VkPipelineLayout mPipelineLayout;
VkPipeline mGraphicsPipeline;
VkCommandPool mCommandPool;
std::vector<VkCommandBuffer> mCommandBuffers;
VkQueue mGraphicsQueue;
VkQueue mPresentQueue;
std::vector<VkSemaphore> mImageAvailableSemaphores;
std::vector<VkSemaphore> mRenderFinishedSemaphores;
std::vector<VkFence> 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<uint8_t>&);
SwapChainSupportDetails querySwapChainSupport(VkPhysicalDevice);
VkSurfaceFormatKHR chooseSwapSurfaceFormat(const std::vector<VkSurfaceFormatKHR>&);
VkPresentModeKHR chooseSwapPresentMode(const std::vector<VkPresentModeKHR>&);
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;
}
};