Compare commits
5 Commits
44a5e2cab9
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c240ad7e3 | |||
| 779c51c2f8 | |||
| f032f152a9 | |||
| 6d34dfc58f | |||
| b196c97cf0 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
|
|
||||||
|
.vscode/*
|
||||||
build/*
|
build/*
|
||||||
|
|||||||
@@ -15,7 +15,12 @@ endif()
|
|||||||
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
|
set(CMAKE_INSTALL_PREFIX ${PROJECT_SOURCE_DIR})
|
||||||
|
|
||||||
#add_subdirectory(src)
|
#add_subdirectory(src)
|
||||||
set(SDL3_DIR "${SDL3_PATH}/cmake")
|
|
||||||
|
set(Vulkan_INCLUDE_DIR "${VULKAN_PATH}/Include")
|
||||||
|
set(Vulkan_LIBRARY "${VULKAN_PATH}/Lib/vulkan-1.lib")
|
||||||
|
find_package(Vulkan REQUIRED)
|
||||||
|
|
||||||
|
set(SDL3_DIR "${VULKAN_PATH}/cmake")
|
||||||
find_package(SDL3 REQUIRED)
|
find_package(SDL3 REQUIRED)
|
||||||
|
|
||||||
# TODO: cascade cmakelists.txt
|
# TODO: cascade cmakelists.txt
|
||||||
@@ -23,15 +28,17 @@ add_executable(ouros
|
|||||||
src/main.cpp
|
src/main.cpp
|
||||||
src/app/App.cpp
|
src/app/App.cpp
|
||||||
src/app/Window.cpp
|
src/app/Window.cpp
|
||||||
|
src/engine/Engine.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
target_include_directories(ouros PRIVATE
|
target_include_directories(ouros PRIVATE
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
"${CMAKE_CURRENT_SOURCE_DIR}/"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src"
|
||||||
|
"${VULKAN_PATH}/Include"
|
||||||
)
|
)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
set(SDL3_DLL "${SDL3_PATH}/lib/x64/SDL3.dll") # assuming youre not arm or 32 bit
|
set(SDL3_DLL "${VULKAN_PATH}/Bin/SDL3.dll")
|
||||||
add_custom_command(TARGET ouros POST_BUILD
|
add_custom_command(TARGET ouros POST_BUILD
|
||||||
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
COMMAND ${CMAKE_COMMAND} -E copy_if_different
|
||||||
"${SDL3_DLL}"
|
"${SDL3_DLL}"
|
||||||
@@ -41,4 +48,5 @@ endif()
|
|||||||
|
|
||||||
target_link_libraries(ouros PRIVATE
|
target_link_libraries(ouros PRIVATE
|
||||||
SDL3::SDL3
|
SDL3::SDL3
|
||||||
|
Vulkan::Vulkan
|
||||||
)
|
)
|
||||||
|
|||||||
15
README.md
15
README.md
@@ -43,8 +43,13 @@ Below is beyond Sascha's guide, but available elsewhere on his github. These are
|
|||||||
- CMake (im using 4.0.0)
|
- CMake (im using 4.0.0)
|
||||||
- C++20 compatible compiler (I use g++12 or MSVC++17) (probably works with mingw but I haven't tested it myself)
|
- C++20 compatible compiler (I use g++12 or MSVC++17) (probably works with mingw but I haven't tested it myself)
|
||||||
- Vulkan compatible gpu drivers (tested with an RTX3070 and an R9700)
|
- Vulkan compatible gpu drivers (tested with an RTX3070 and an R9700)
|
||||||
- SDL3 (im using version 3.4.4)
|
- Vulkan SDK (https://vulkan.lunarg.com/sdk/home)
|
||||||
|
- SDL3*
|
||||||
|
- VOC*
|
||||||
|
- GLM*
|
||||||
- Will add more as the project grows
|
- Will add more as the project grows
|
||||||
|
|
||||||
|
*packaged with the Vulkan SDK
|
||||||
|
|
||||||
### Clone respository:
|
### Clone respository:
|
||||||
```bash
|
```bash
|
||||||
@@ -52,7 +57,8 @@ $ git clone https://git.vxbard.net/homeburger/ouros.git --recursive
|
|||||||
```
|
```
|
||||||
### Configure and build project:
|
### Configure and build project:
|
||||||
```bash
|
```bash
|
||||||
$ cmake -S . -B build -DSDL3_PATH="${SDL3_INSTALL_PATH}" # either set this variable or substitute it in
|
$ cmake -S . -B build \
|
||||||
|
-DVULKAN_PATH="${VULKAN_INSTALL_PATH}" # either set this variable or substitute it in
|
||||||
$ cmake --build build -j
|
$ cmake --build build -j
|
||||||
```
|
```
|
||||||
### Execute application:
|
### Execute application:
|
||||||
@@ -63,10 +69,11 @@ $ ./build/ouros
|
|||||||
```
|
```
|
||||||
For control on debugging:
|
For control on debugging:
|
||||||
```bash
|
```bash
|
||||||
$ ./build/ouros --debug 0b00111111
|
$ ./build/ouros --debug=0b00111111
|
||||||
```
|
```
|
||||||
where each bit in the mask corresponds to a debug level, in order: unused, unused, fatal, trace, error, warning, notice, and info. `0b1111111` enables all debug messages.
|
where each bit in the mask corresponds to a debug level, in order: unused, unused, fatal, trace, error, warning, notice, and info. `0b1111111` enables all debug messages.
|
||||||
|
|
||||||
## Additional Resources
|
## Additional Resources
|
||||||
- https://howtovulkan.com/
|
- https://howtovulkan.com/, primary guide, most up-to-date (2026, Vulkan v1.4)
|
||||||
|
- https://vkguide.dev/, Vulkan v1.3, but provides a lot of guidance on a more robustly architectured Vulkan app
|
||||||
- Will add more as I use them
|
- Will add more as I use them
|
||||||
|
|||||||
@@ -1,6 +1,9 @@
|
|||||||
|
|
||||||
#include "App.hpp"
|
#include "App.hpp"
|
||||||
|
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include "utils/utils.hpp"
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
App::App() {
|
App::App() {
|
||||||
@@ -16,6 +19,7 @@ void App::init() {
|
|||||||
utils::debugPrint(__FUNCTION__, __LINE__, "Init app.", utils::DebugLevel::Trace);
|
utils::debugPrint(__FUNCTION__, __LINE__, "Init app.", utils::DebugLevel::Trace);
|
||||||
|
|
||||||
window_ = new Window();
|
window_ = new Window();
|
||||||
|
engine_ = new Engine(window_);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,17 +27,25 @@ int App::run() {
|
|||||||
|
|
||||||
utils::debugPrint(__FUNCTION__, __LINE__, "Run app.", utils::DebugLevel::Trace);
|
utils::debugPrint(__FUNCTION__, __LINE__, "Run app.", utils::DebugLevel::Trace);
|
||||||
|
|
||||||
bool quit = false;
|
SDL_Event event;
|
||||||
while (!quit) {
|
while (window_->open()) {
|
||||||
// app loop for as long as the window is open
|
// app loop for as long as the window is open
|
||||||
// other threads might be able to change quit to true to auto close
|
|
||||||
|
|
||||||
SDL_Event event;
|
// pass events to the window
|
||||||
while(SDL_PollEvent(&event)) { // TODO: pass event handling to window
|
while(SDL_PollEvent(&event) != 0) {
|
||||||
if(event.type == SDL_EVENT_QUIT ) {
|
window_->handleEvent(event);
|
||||||
quit = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// pass vulkan handling to engine
|
||||||
|
// call engine.render() or something
|
||||||
|
// engine has a pointer to window so can handle pushing to the screen
|
||||||
|
|
||||||
|
if(window_->rendering()) {
|
||||||
|
engine_->draw();
|
||||||
|
} else {
|
||||||
|
std::this_thread::sleep_for(std::chrono::milliseconds(100)); // wait until the window is visible again
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// SDL teardown handled in window destructor
|
// SDL teardown handled in window destructor
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
|
#include "engine/Engine.hpp"
|
||||||
|
|
||||||
class App {
|
class App {
|
||||||
|
|
||||||
@@ -10,7 +11,7 @@ public:
|
|||||||
App();
|
App();
|
||||||
~App() = default;
|
~App() = default;
|
||||||
|
|
||||||
// excecute, called from main()
|
// excecute, called from main(). returns after window closes
|
||||||
int run();
|
int run();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -19,5 +20,8 @@ private:
|
|||||||
void init();
|
void init();
|
||||||
|
|
||||||
Window* window_;
|
Window* window_;
|
||||||
|
Engine* engine_;
|
||||||
|
|
||||||
|
bool rendering_ = true;
|
||||||
|
|
||||||
};
|
};
|
||||||
@@ -1,6 +1,8 @@
|
|||||||
|
|
||||||
#include "Window.hpp"
|
#include "Window.hpp"
|
||||||
|
|
||||||
|
#include <SDL3/SDL_events.h>
|
||||||
|
|
||||||
Window::Window() {
|
Window::Window() {
|
||||||
|
|
||||||
(void)init();
|
(void)init();
|
||||||
@@ -9,15 +11,34 @@ Window::Window() {
|
|||||||
|
|
||||||
Window::~Window() {
|
Window::~Window() {
|
||||||
|
|
||||||
SDL_DestroyWindow(window_);
|
SDL_DestroyWindow(sdlWindow_);
|
||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int Window::init() {
|
int Window::init() {
|
||||||
|
|
||||||
window_ = SDL_CreateWindow("How to Vulkan", 1280u, 720u, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
sdlWindow_ = SDL_CreateWindow("Ouros: Vulkan", 1280u, 720u, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE);
|
||||||
|
|
||||||
return (window_ == nullptr);
|
if(sdlWindow_ != nullptr) {
|
||||||
|
rendering_ = true;
|
||||||
|
open_ = true;
|
||||||
|
return 0;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Window::handleEvent(SDL_Event& event) {
|
||||||
|
|
||||||
|
if(event.type == SDL_EVENT_QUIT ) {
|
||||||
|
open_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(event.type == SDL_EVENT_WINDOW_MINIMIZED) {
|
||||||
|
rendering_ = false;
|
||||||
|
} else if(event.type == SDL_EVENT_WINDOW_RESTORED) {
|
||||||
|
rendering_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "SDL3/SDL.h"
|
#include "SDL3/SDL.h"
|
||||||
#include "SDL3/SDL_Vulkan.h"
|
#include "SDL3/SDL_vulkan.h"
|
||||||
|
|
||||||
// reference: https://wiki.libsdl.org/SDL3/SDL_CreateWindow
|
// reference: https://wiki.libsdl.org/SDL3/SDL_CreateWindow
|
||||||
|
|
||||||
@@ -13,10 +13,22 @@ public:
|
|||||||
Window();
|
Window();
|
||||||
~Window();
|
~Window();
|
||||||
|
|
||||||
|
void handleEvent(SDL_Event& event);
|
||||||
|
|
||||||
|
bool rendering() { return rendering_; }
|
||||||
|
bool open() { return open_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
// launches window
|
||||||
int init();
|
int init();
|
||||||
|
|
||||||
SDL_Window* window_;
|
// this window class will eventually hold mouse, keyboard, audio, etc. interfaces, like an SDL3 hub
|
||||||
|
// app will be able to attach callbacks for mouse and keyboard events
|
||||||
|
|
||||||
|
SDL_Window* sdlWindow_;
|
||||||
|
|
||||||
|
bool rendering_ = false;
|
||||||
|
bool open_ = false;
|
||||||
|
|
||||||
};
|
};
|
||||||
50
src/engine/Engine.cpp
Normal file
50
src/engine/Engine.cpp
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
|
||||||
|
#include "Engine.hpp"
|
||||||
|
|
||||||
|
#include "vulkan/vulkan.h"
|
||||||
|
|
||||||
|
#include "utils/utils.hpp"
|
||||||
|
|
||||||
|
Engine::Engine(Window* window): window_(window) {
|
||||||
|
|
||||||
|
init();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::init() {
|
||||||
|
|
||||||
|
VkApplicationInfo appInfo {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
|
||||||
|
.pApplicationName = "How to Vulkan",
|
||||||
|
.apiVersion = VK_API_VERSION_1_3
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t instanceExtensionsCount = 0;
|
||||||
|
char const* const* instanceExtensions{ SDL_Vulkan_GetInstanceExtensions(&instanceExtensionsCount) };
|
||||||
|
|
||||||
|
VkInstanceCreateInfo instanceCI {
|
||||||
|
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
|
||||||
|
.pApplicationInfo = &appInfo,
|
||||||
|
.enabledExtensionCount = instanceExtensionsCount,
|
||||||
|
.ppEnabledExtensionNames = instanceExtensions,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkInstance instance;
|
||||||
|
if(vkCreateInstance(&instanceCI, nullptr, &instance) == VK_SUCCESS) {
|
||||||
|
utils::debugPrint(__FUNCTION__, __LINE__, "Vulkan instance successfully created.", utils::DebugLevel::Info);
|
||||||
|
} else {
|
||||||
|
utils::debugPrint(__FUNCTION__, __LINE__, "Error creating Vulkan instance", utils::DebugLevel::Error);
|
||||||
|
}
|
||||||
|
|
||||||
|
// next steps:
|
||||||
|
// device selection and setup
|
||||||
|
// queue creation
|
||||||
|
// vulkan memory allocator
|
||||||
|
// create vulkan surface
|
||||||
|
// attach surface to window
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Engine::draw() {
|
||||||
|
|
||||||
|
}
|
||||||
27
src/engine/Engine.hpp
Normal file
27
src/engine/Engine.hpp
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "app/Window.hpp"
|
||||||
|
|
||||||
|
#define VK_USE_PLATFORM_WIN32_KHR 1
|
||||||
|
|
||||||
|
class Engine {
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Engine(Window* window);
|
||||||
|
~Engine() = default;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
|
||||||
|
// draw is called every render iteration in that while loop
|
||||||
|
void draw();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// might get rid of this
|
||||||
|
|
||||||
|
// TODO: smart pointers probably would be smart
|
||||||
|
Window* window_;
|
||||||
|
|
||||||
|
};
|
||||||
@@ -22,6 +22,7 @@ int main(int argc, char *argv[]) {
|
|||||||
// maybe do some exceptions here
|
// maybe do some exceptions here
|
||||||
App app = App();
|
App app = App();
|
||||||
|
|
||||||
|
// executes for as long as the window is open
|
||||||
return app.run();
|
return app.run();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,9 +5,10 @@
|
|||||||
#include <iomanip>
|
#include <iomanip>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
// TODO: might move a lot of this into a debug.h file
|
// TODO: might move a lot of this into a debug.hpp file
|
||||||
// TODO: logging ? but i dont care enough
|
// TODO: logging ? but i dont care enough
|
||||||
|
|
||||||
|
// do i classify this up? global static functions kinda scare me but i mean otrherwise itll be a global singleton so idk
|
||||||
namespace utils {
|
namespace utils {
|
||||||
|
|
||||||
enum DebugLevel : size_t {
|
enum DebugLevel : size_t {
|
||||||
@@ -31,27 +32,32 @@ namespace utils {
|
|||||||
"Extra1",
|
"Extra1",
|
||||||
"Extra2"
|
"Extra2"
|
||||||
};
|
};
|
||||||
// the idea is to have a debug bitmask, maybe 8 bits wide, where the bits can be set via compiler flags
|
|
||||||
|
|
||||||
|
// stores the input that determines which debug statements to filter
|
||||||
inline uint8_t debugMask;
|
inline uint8_t debugMask;
|
||||||
|
|
||||||
|
// print to standard output in a normalized format, includes the trace and debug level
|
||||||
static void debugPrint(const char* function, int line, std::string message, size_t debugLevel) {
|
static void debugPrint(const char* function, int line, std::string message, size_t debugLevel) {
|
||||||
|
|
||||||
if(!(debugMask >> debugLevel)) return; // then ignore this debug level
|
if(!((debugMask >> debugLevel) & 1)) return; // then ignore this debug level
|
||||||
|
|
||||||
std::cout << "[ " << std::left << std::setw(16) << function << ": " << std::right << std::setw(4) << line << ", " << std::left << std::setw(8) << debugTypeStrings[debugLevel] << " ] " << message << std::endl;
|
std::cout << "[ " << std::left << std::setw(16) << function << ": " << std::right << std::setw(4) << line << ", " << std::left << std::setw(8) << debugTypeStrings[debugLevel] << " ] " << message << std::endl;
|
||||||
|
// TODO: add timestamps
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// process the input from the executable (0bxxxxxxxx)
|
||||||
static void parseDebugMaskString(std::string& debugMaskString) {
|
static void parseDebugMaskString(std::string& debugMaskString) {
|
||||||
std::string value = debugMaskString;
|
std::string value = debugMaskString;
|
||||||
if(value.rfind("0b", 0) == 0) {
|
if(value.rfind("0b", 0) == 0) { // may allow other inputs in the future, this is just a binary byte
|
||||||
value = value.substr(2); // strip the binary literal identifier
|
value = value.substr(2); // strip the binary literal identifier
|
||||||
|
debugMask = static_cast<uint8_t>(std::stoul(value, nullptr, 2)); // interpret a string as a uint
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Unsupported debug key." << std::endl;
|
std::cout << "Unsupported debug key." << std::endl;
|
||||||
|
debugMask = 0; // disable debug statements
|
||||||
}
|
}
|
||||||
debugMask = static_cast<uint8_t>(std::stoul(value, nullptr, 2)); // interpret a string as a uint
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user