VulkanSDL3/include/vulkanapp.hh

141 lines
4.3 KiB
C++

#pragma once
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_events.h>
#include <cstdint>
#include <vector>
#include <optional>
#include <vulkan/vulkan.h>
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;
#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<uint32_t> graphicsFamily;
std::optional<uint32_t> presentFamily;
bool complete() {
return graphicsFamily.has_value() && presentFamily.has_value();
}
};
struct SwapChainSupportDetails {
VkSurfaceCapabilitiesKHR capabilities;
std::vector<VkSurfaceFormatKHR> formats;
std::vector<VkPresentModeKHR> presentModes;
};
class VulkanApp {
public:
VulkanApp(const uint32_t& _w, const uint32_t& _h) :
mWin(nullptr), mWidth(_w), mHeight(_h) {}
void init();
void loop();
void cleanup();
private:
// SDL2
SDL_Window *mWin;
SDL_Event mEvent;
// Not tied to library
uint32_t mWidth;
uint32_t mHeight;
bool mActive = false;
bool mResized = false;
bool mMinimized = false;
// Vulkan
VkInstance mInstance;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
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();
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) {
fprintf(stderr, "Validation Layer [Error/Warning]: %s \n", pCallbackData->pMessage);
} else if(messageType & VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT) {
fprintf(stderr, "Validation Layer [General]: %s \n", pCallbackData->pMessage);
} else {
fprintf(stderr, "Validation Layer: %s \n", pCallbackData->pMessage);
}
return VK_FALSE;
}
};