Small tweaks
This commit is contained in:
parent
65cd03961d
commit
e82355d05d
4
.gitignore
vendored
4
.gitignore
vendored
@ -103,7 +103,9 @@ CMakeUserPresets.json
|
||||
# Other
|
||||
.cache/
|
||||
.vscode/
|
||||
build/
|
||||
build*/
|
||||
|
||||
.kdev4/
|
||||
*.kdev4
|
||||
|
||||
*_old.*
|
||||
|
||||
3
.gitmodules
vendored
3
.gitmodules
vendored
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
18
include/vk_types.hh
Normal 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;
|
||||
};
|
||||
72
src/main.cc
72
src/main.cc
@ -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();
|
||||
}
|
||||
|
||||
@ -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
thirdparty/vk-bootstrap
vendored
1
thirdparty/vk-bootstrap
vendored
@ -1 +0,0 @@
|
||||
Subproject commit 0437431fd055ac362d388a006a0fd861a6c945f2
|
||||
Loading…
x
Reference in New Issue
Block a user