Small tweaks

This commit is contained in:
macmacmac 2025-08-08 13:42:13 -04:00
parent 65cd03961d
commit e82355d05d
8 changed files with 106 additions and 131 deletions

4
.gitignore vendored
View File

@ -103,7 +103,9 @@ CMakeUserPresets.json
# Other
.cache/
.vscode/
build/
build*/
.kdev4/
*.kdev4
*_old.*

3
.gitmodules vendored
View File

@ -1,6 +1,3 @@
[submodule "thirdparty/vk-bootstrap"]
path = thirdparty/vk-bootstrap
url = https://github.com/charles-lunarg/vk-bootstrap.git
[submodule "thirdparty/SDL"]
path = thirdparty/SDL
url = https://github.com/libsdl-org/SDL.git

View File

@ -1,10 +1,11 @@
cmake_minimum_required(VERSION 3.10)
project(vksdlproj VERSION 0.2.0 LANGUAGES C CXX)
SET(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
set(EXE_NAME project)
#set(CMAKE_BUILD_RPATH_USE_ORIGIN TRUE)
#set(CMAKE_POSITION_INDEPENDENT_CODE TRUE)
set(EXE_NAME sdl3vkgame)
set(PROGRAM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vulkanapp.cc)
set(PROGRAM_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/src/vk_app.cc)
option(SDL3_NONSYSTEM "Use SDL3 from folder in source tree" ON)
@ -31,8 +32,6 @@ else()
find_package(SDL3 REQUIRED CONFIG REQUIRED COMPONENTS SDL3-shared)
endif()
add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/thirdparty/vk-bootstrap)
find_package(Vulkan REQUIRED COMPONENTS glslc)
# Compile each shader
@ -76,5 +75,4 @@ endif()
# Linking
target_link_libraries(${EXE_NAME} PRIVATE SDL3::SDL3)
target_link_libraries(${EXE_NAME} PRIVATE Vulkan::Vulkan)
target_link_libraries(${EXE_NAME} PRIVATE vk-bootstrap::vk-bootstrap)
target_link_libraries(${EXE_NAME} PRIVATE Vulkan::Vulkan) # TODO: change this to Vulkna::Headers and use loader

View File

@ -1,15 +1,19 @@
#pragma once
#include <SDL3/SDL_video.h>
#include <SDL3/SDL_events.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL_log.h>
#include <SDL3/SDL_vulkan.h>
#include <cstdint>
#include <vulkan/vulkan.h>
#include <stdexcept>
#include <set>
#include <limits>
#include <algorithm>
#include <vector>
#include <optional>
#include <cstdio>
#include <vulkan/vulkan.h>
#include "vk_types.hh"
const std::vector<const char*> validationLayers = {
"VK_LAYER_KHRONOS_validation"
@ -21,56 +25,42 @@ const std::vector<const char*> deviceExtensions = {
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) {}
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(); }
void init();
void loop();
void 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; }
inline void minimized(bool _v) { mMinimized = _v; }
inline void resized(bool _v) { mResized = _v; }
private:
// SDL2
// SDL3
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;
const char *mTitle;
bool mResized;
bool mMinimized;
#ifdef NDEBUG
const bool mEnableValidationLayers = false;
#else
const bool mEnableValidationLayers = true;
#endif
// Vulkan
VkInstance mInstance;
VkPhysicalDevice mPhysicalDevice = VK_NULL_HANDLE;
VkPhysicalDevice mPhysicalDevice;
VkDevice mLogicalDevice;
VkSurfaceKHR mSurface;
@ -95,7 +85,6 @@ private:
std::vector<VkSemaphore> mRenderFinishedSemaphores;
std::vector<VkFence> mInFlightFences;
VkDebugUtilsMessengerEXT mDebugMessenger;
void createInstance();
@ -116,6 +105,7 @@ private:
void recordCommandBuffer(VkCommandBuffer, uint32_t);
void drawFrame();
void cleanup();
QueueFamilyIndices findQueueFamilies(VkPhysicalDevice);
bool isDeviceSuitable(VkPhysicalDevice);
@ -135,11 +125,11 @@ private:
(void)pUserData;
if(messageSeverity >= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
fprintf(stderr, "Validation Layer [Error/Warning]: %s \n", pCallbackData->pMessage);
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) {
fprintf(stderr, "Validation Layer [General]: %s \n", pCallbackData->pMessage);
SDL_Log("Validation Layer [General]: %s \n", pCallbackData->pMessage);
} else {
fprintf(stderr, "Validation Layer: %s \n", pCallbackData->pMessage);
SDL_Log("Validation Layer: %s \n", pCallbackData->pMessage);
}
return VK_FALSE;

18
include/vk_types.hh Normal file
View File

@ -0,0 +1,18 @@
#pragma once
#include <vulkan/vulkan.hpp>
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;
};

View File

@ -1,95 +1,61 @@
#define SDL_MAIN_USE_CALLBACKS
#include <SDL3/SDL_main.h>
#include <SDL3/SDL_init.h>
#include <SDL3/SDL.h>
#include "vulkanapp.hh"
#include <exception>
#include "vk_app.hh"
constexpr uint32_t winInitWidth = 1024;
constexpr uint32_t winInitHeight = 1024;
struct AppContext {
VulkanApp vkapp;
SDL_AppResult appQuit = SDL_APP_CONTINUE;
AppContext(const uint32_t& _w, const uint32_t& _h) : vkapp(_w, _h) {
this->vkapp.init();
}
~AppContext() {
this->vkapp.cleanup();
}
};
SDL_AppResult SDL_Fail() {
SDL_LogError(SDL_LOG_CATEGORY_ERROR, "Error: %s", SDL_GetError());
return SDL_APP_FAILURE;
}
SDL_AppResult SDL_AppInit(void **appstate, int argc, char **argv) {
(void)argc;
(void)argv;
if(!SDL_Init(SDL_INIT_VIDEO))
return SDL_Fail();
*appstate = new VulkanApp("Vulkan+SDL3 App", winInitWidth, winInitHeight);
VulkanApp* app = static_cast<VulkanApp*>(*appstate);
try {
*appstate = new AppContext(winInitWidth, winInitHeight);
} catch(const std::exception& except) {
fprintf(stderr, "Error! %s\n", except.what());
return SDL_APP_FAILURE;
}
return SDL_APP_CONTINUE;
return app->init();
}
SDL_AppResult SDL_AppEvent(void *appstate, SDL_Event *event) {
AppContext* app = static_cast<AppContext*>(appstate);
VulkanApp* app = static_cast<VulkanApp*>(appstate);
switch(event->type) {
case SDL_EVENT_QUIT:
app->appQuit = SDL_APP_SUCCESS;
app->mAppState = SDL_APP_SUCCESS;
break;
case SDL_EVENT_WINDOW_RESIZED:
app->vkapp.resized(true);
app->resized(true);
break;
case SDL_EVENT_WINDOW_MINIMIZED:
app->vkapp.minimized(true);
app->minimized(true);
break;
case SDL_EVENT_WINDOW_RESTORED:
app->vkapp.minimized(false);
app->minimized(false);
break;
default:
break;
}
return SDL_APP_CONTINUE;
return app->mAppState;
}
SDL_AppResult SDL_AppIterate(void *appstate) {
AppContext* app = static_cast<AppContext*>(appstate);
VulkanApp* app = static_cast<VulkanApp*>(appstate);
try {
app->vkapp.loop();
} catch(const std::exception& except) {
fprintf(stderr, "Error! %s\n", except.what());
return SDL_APP_FAILURE;
}
return app->appQuit;
return app->loop();
}
void SDL_AppQuit(void *appstate, SDL_AppResult result) {
AppContext* app = static_cast<AppContext*>(appstate);
VulkanApp* app = static_cast<VulkanApp*>(appstate);
#ifndef NDEBUG
if(result == SDL_APP_FAILURE)
fputs("Program failure, shutting down\n", stderr);
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Program failure occured, shutting down");
else
puts("Program shutting down, no errors.");
if(app)
delete app;
SDL_LogInfo(SDL_LOG_CATEGORY_APPLICATION, "Program shutting down, no errors.");
#endif
// Cleanup
if(app) delete app;
SDL_Quit();
}

View File

@ -1,12 +1,4 @@
#include "vulkanapp.hh"
#include <SDL3/SDL.h>
#include <SDL3/SDL_vulkan.h>
#include <stdexcept>
#include <set>
#include <limits>
#include <algorithm>
#include "vk_app.hh"
// Validator stuff
VkResult CreateDebugUtilsMessengerEXT(VkInstance instance,
@ -159,7 +151,7 @@ VkSurfaceFormatKHR VulkanApp::chooseSwapSurfaceFormat(const std::vector<VkSurfac
VkPresentModeKHR VulkanApp::chooseSwapPresentMode(const std::vector<VkPresentModeKHR>& availablePresentModes) {
for (const VkPresentModeKHR& availablePresentMode : availablePresentModes) {
if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) {
if (availablePresentMode == VK_PRESENT_MODE_FIFO_KHR) {
return availablePresentMode;
}
}
@ -303,12 +295,18 @@ void VulkanApp::drawFrame() {
currentFrame = (currentFrame + 1) % MAX_FRAMES_IN_FLIGHT;
}
void VulkanApp::init() {
SDL_AppResult VulkanApp::init() {
// Initialize SDL3
SDL_Init(SDL_INIT_VIDEO);
// if(!SDL_Vulkan_LoadLibrary(nullptr)) {
// std::string err = "Could not load vulkan library! " + std::string(SDL_GetError()) + "\n";
//
// throw std::runtime_error(err);
// }
// Create the window
mWin = SDL_CreateWindow("Vulkan+SDL2 Application",
mWin = SDL_CreateWindow(mTitle,
mWidth,
mHeight,
SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE
@ -319,6 +317,9 @@ void VulkanApp::init() {
throw std::runtime_error(err);
}
SDL_SetWindowMaximumSize(mWin, mWidth, mHeight);
SDL_SetWindowMinimumSize(mWin, mWidth / 2, mHeight / 2);
// Vulkan stuff from here
createInstance();
setupDebugMessenger();
@ -328,7 +329,7 @@ void VulkanApp::init() {
throw std::runtime_error("Could not create Vulkan surface!");
}
// TODO: Replace some of this crap with vkbootstrap code
// TODO: Replace some of this crap with vulkan hpp code
selectPhysicalDevice();
createLogicalDevice();
createSwapChain();
@ -339,10 +340,12 @@ void VulkanApp::init() {
createCommandPool();
createCommandBuffer();
createSyncObjects();
return SDL_APP_CONTINUE;
}
void VulkanApp::createInstance() {
if (enableValidationLayers && !checkValidationLayerSupport()) {
if (mEnableValidationLayers && !checkValidationLayerSupport()) {
throw std::runtime_error("Validation layers requested, but not available!");
}
@ -352,7 +355,7 @@ void VulkanApp::createInstance() {
// Put extensions into vector
std::vector<const char*> extensionNames(extensionArr, extensionArr + extensionCount);
if(enableValidationLayers)
if(mEnableValidationLayers)
extensionNames.push_back(VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
// App info
@ -362,7 +365,7 @@ void VulkanApp::createInstance() {
appInfo.applicationVersion = VK_MAKE_VERSION(1, 1, 0);
appInfo.pEngineName = "RAPT2";
appInfo.engineVersion = VK_MAKE_VERSION(1, 1, 0);
appInfo.apiVersion = VK_API_VERSION_1_3;
appInfo.apiVersion = VK_API_VERSION_1_1;
// Extensions
VkInstanceCreateInfo createInfo{};
@ -374,7 +377,7 @@ void VulkanApp::createInstance() {
// Debug handling
VkDebugUtilsMessengerCreateInfoEXT debugCreateInfo{};
if(enableValidationLayers) {
if(mEnableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
@ -456,7 +459,7 @@ void VulkanApp::createLogicalDevice() {
createInfo.enabledExtensionCount = static_cast<uint32_t>(deviceExtensions.size());
createInfo.ppEnabledExtensionNames = deviceExtensions.data();
if (enableValidationLayers) {
if (mEnableValidationLayers) {
createInfo.enabledLayerCount = static_cast<uint32_t>(validationLayers.size());
createInfo.ppEnabledLayerNames = validationLayers.data();
} else {
@ -836,7 +839,7 @@ bool VulkanApp::checkValidationLayerSupport() {
}
void VulkanApp::setupDebugMessenger() {
if (!enableValidationLayers) return;
if (!mEnableValidationLayers) return;
VkDebugUtilsMessengerCreateInfoEXT createInfo;
createInfo = {};
@ -854,7 +857,7 @@ void VulkanApp::setupDebugMessenger() {
}
}
void VulkanApp::loop() {
SDL_AppResult VulkanApp::loop() {
if(mWin == nullptr) {
std::string err = "Could not find window " + std::string(SDL_GetError()) + "\n";
throw std::runtime_error(err);
@ -863,6 +866,8 @@ void VulkanApp::loop() {
if(!mMinimized) drawFrame();
vkDeviceWaitIdle(mLogicalDevice);
return SDL_APP_CONTINUE;
}
void VulkanApp::cleanup() {
@ -883,7 +888,7 @@ void VulkanApp::cleanup() {
vkDestroyDevice(mLogicalDevice, nullptr);
if (enableValidationLayers)
if (mEnableValidationLayers)
DestroyDebugUtilsMessengerEXT(mInstance, mDebugMessenger, nullptr);
vkDestroySurfaceKHR(mInstance, mSurface, nullptr);

@ -1 +0,0 @@
Subproject commit 0437431fd055ac362d388a006a0fd861a6c945f2