Compare commits

...

96 Commits

Author SHA1 Message Date
Alexandre
597bd4c04e Update engine.h
Some checks failed
Build VulkanEngine / build (push) Failing after 14m50s
Build VulkanEngine / nix (push) Successful in 2m44s
Build VulkanEngine / debug (push) Successful in 2m30s
Build VulkanEngine / release (BUNDLE) (push) Successful in 2m39s
Build VulkanEngine / release (PORTABLE) (push) Successful in 2m53s
Build VulkanEngine / notify (push) Successful in 2s
2026-10-13 09:35:30 +02:00
Alexandre
207cdbf2a3 Fixed some issues
All checks were successful
Build VulkanEngine / build (push) Successful in 5m10s
Build VulkanEngine / nix (push) Successful in 3m22s
Build VulkanEngine / debug (push) Successful in 3m16s
Build VulkanEngine / release (BUNDLE) (push) Successful in 3m45s
Build VulkanEngine / release (PORTABLE) (push) Successful in 3m35s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-13 09:34:01 +02:00
Alexandre
f724ecc09d Added debug artefact
All checks were successful
Build VulkanEngine / build (push) Successful in 4m52s
Build VulkanEngine / nix (push) Successful in 3m15s
Build VulkanEngine / debug (push) Successful in 3m16s
Build VulkanEngine / release (BUNDLE) (push) Successful in 3m35s
Build VulkanEngine / release (PORTABLE) (push) Successful in 3m38s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-12 13:17:05 +02:00
Alexandre
65a715bd12 Fixed nix build
All checks were successful
Build VulkanEngine / build (push) Successful in 4m59s
Build VulkanEngine / nix (push) Successful in 3m38s
Build VulkanEngine / release (BUNDLE) (push) Successful in 3m43s
Build VulkanEngine / release (PORTABLE) (push) Successful in 3m35s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-10 14:30:00 +02:00
Alexandre
d2cbc2e073 Update build.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m37s
Build VulkanEngine / nix (push) Successful in 3m28s
Build VulkanEngine / release (BUNDLE) (push) Successful in 3m49s
Build VulkanEngine / release (PORTABLE) (push) Successful in 3m49s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-10 12:40:00 +02:00
Alexandre
9b7b0af38d Update build_linux.yaml
All checks were successful
Build VulkanEngine / nix (push) Successful in 3m19s
Build VulkanEngine / release (BUNDLE) (push) Successful in 3m35s
Build VulkanEngine / release (PORTABLE) (push) Successful in 3m54s
Build VulkanEngine / notify (push) Successful in 19s
2026-10-09 23:18:29 +02:00
Alexandre
e2a2833aae Tring to fix things
Some checks failed
Build VulkanEngine / nix (push) Has been cancelled
Build VulkanEngine / release (BUNDLE) (push) Has been cancelled
Build VulkanEngine / release (PORTABLE) (push) Has been cancelled
Build VulkanEngine / notify (push) Has been cancelled
2026-10-09 23:17:15 +02:00
Alexandre
4874a49aaa Fixed dependency for glibc or smth ig
Some checks failed
Build VulkanEngine / nix (push) Successful in 5m53s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m59s
Build VulkanEngine / release (PORTABLE) (push) Failing after 2m58s
Build VulkanEngine / notify (push) Successful in 3s
2026-10-09 22:59:00 +02:00
Alexandre
bbf7950bfa Update CMakeLists.txt
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m23s
Build VulkanEngine / release (BUNDLE) (push) Failing after 3m2s
Build VulkanEngine / release (PORTABLE) (push) Failing after 3m3s
Build VulkanEngine / notify (push) Successful in 3s
2026-10-09 22:43:00 +02:00
Alexandre
0313543c06 Update CMakeLists.txt
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m33s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m22s
Build VulkanEngine / release (PORTABLE) (push) Failing after 2m20s
Build VulkanEngine / notify (push) Successful in 5s
2026-10-09 21:30:30 +02:00
Alexandre
697d604d5a Update build_linux.yaml
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m11s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m57s
Build VulkanEngine / release (PORTABLE) (push) Failing after 3m7s
Build VulkanEngine / notify (push) Successful in 5s
2026-10-09 21:16:30 +02:00
Alexandre
f12bcf9b7c Update CMakeLists.txt
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m21s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m42s
Build VulkanEngine / release (PORTABLE) (push) Failing after 2m47s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-09 20:57:01 +02:00
Alexandre
b5bae50f55 Switched to Volk
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m14s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m24s
Build VulkanEngine / release (PORTABLE) (push) Failing after 2m17s
Build VulkanEngine / notify (push) Successful in 5s
2026-10-09 20:50:02 +02:00
Alexandre
089e7493b6 Another attempt
Some checks failed
Build VulkanEngine / nix (push) Successful in 3m12s
Build VulkanEngine / release (BUNDLE) (push) Failing after 2m13s
Build VulkanEngine / release (PORTABLE) (push) Failing after 2m10s
Build VulkanEngine / notify (push) Successful in 4s
2026-10-09 20:39:35 +02:00
Alexandre
e6a2fb9c22 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 3m51s
2026-10-09 13:25:14 +02:00
Alexandre
ffa06fb97f Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m7s
2026-10-07 13:43:44 +02:00
Alexandre
d0bb078f2f Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 3m31s
2026-10-07 13:42:58 +02:00
Alexandre
88dba64752 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 3m35s
2026-10-07 13:37:45 +02:00
Alexandre
eb196fffd6 Update build_linux.yaml
All checks were successful
Build VulkanEngine / build (push) Successful in 3m39s
2026-10-07 13:31:21 +02:00
Alexandre
5626e6ead8 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 3m8s
2026-10-07 13:24:59 +02:00
Alexandre
a78a17fdde Tweaked the action
Some checks failed
Build VulkanEngine / build (push) Failing after 3s
2026-10-07 13:24:28 +02:00
Alexandre
9515c4293e Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m39s
2026-10-07 12:51:28 +02:00
Alexandre
f43f5ea101 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m51s
2026-10-07 12:48:02 +02:00
Alexandre
0ff518ce9f Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m44s
2026-10-06 21:29:59 +02:00
Alexandre
610039cf16 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 17s
2026-10-06 21:29:20 +02:00
Alexandre
f37b7676d3 Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 2m43s
2026-10-06 21:24:42 +02:00
Alexandre
fda45a1bfe Tweaked the action and the cmake
Some checks failed
Build VulkanEngine / build (push) Failing after 2m49s
2026-10-06 21:20:13 +02:00
Alexandre
052248a699 Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 2m13s
2026-10-06 17:08:32 +02:00
Alexandre
4468080472 Updated CMAKE and worflow
Some checks failed
Build VulkanEngine / build (push) Failing after 2m15s
2026-10-06 17:05:29 +02:00
Alexandre
df9aa831ac Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m30s
2026-10-06 16:27:36 +02:00
Alexandre
bc45fe99ab Oops mb
Some checks failed
Build VulkanEngine / build (push) Failing after 2m37s
2026-10-06 16:19:30 +02:00
Alexandre
24e2090fb5 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-10-06 16:18:49 +02:00
Alexandre
08958cb66f Update build_linux.yaml 2026-10-06 16:18:06 +02:00
Alexandre
01a508edb2 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 44s
2026-10-06 16:14:37 +02:00
Alexandre
1ccfae3d98 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m32s
2026-10-06 16:13:02 +02:00
Alexandre
dcac87d621 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 2m26s
2026-10-06 15:19:09 +02:00
Alexandre
424a454d1c Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 2m25s
2026-10-06 15:14:41 +02:00
Alexandre
c65ea58e84 Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 2m0s
2026-10-06 15:11:30 +02:00
Alexandre
aca3015e12 Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 2m21s
2026-10-06 15:06:02 +02:00
Alexandre
ddd7ee7a0d Update CMakeLists.txt
Some checks failed
Build VulkanEngine / build (push) Failing after 1m56s
2026-10-06 14:58:38 +02:00
Alexandre
3ca60e61eb Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m58s
2026-10-06 14:55:11 +02:00
Alexandre
2774f27049 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 41s
2026-10-06 14:54:06 +02:00
Alexandre
6feb6b98b5 Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 54s
2026-10-06 14:52:48 +02:00
Alexandre
05c9bf672b Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 41s
2026-10-06 14:51:14 +02:00
Alexandre
e6e7cf394f Update build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 49s
2026-10-06 14:48:51 +02:00
Alexandre
663d7ed70a Tweaked the cmake and workflow
Some checks failed
Build VulkanEngine / build (push) Failing after 42s
2026-10-06 14:43:37 +02:00
6ebe7143a8 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 37s
2026-10-06 14:33:34 +02:00
3c4be610c5 Actualiser .gitea/workflows/build_linux.yaml
Some checks are pending
Build VulkanEngine / build (push) Waiting to run
2026-10-06 14:33:10 +02:00
239b509ca8 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m18s
2026-10-06 13:45:52 +02:00
620daad6b7 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 33m44s
2026-10-06 12:06:53 +02:00
be672eb3ce Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m56s
2026-10-06 12:03:57 +02:00
a14a1f7b53 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-10-06 11:21:17 +02:00
12667eb1f8 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m13s
2026-10-06 11:16:39 +02:00
02b1a3a41a Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m9s
2026-10-06 11:13:15 +02:00
961c75ce94 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m14s
2026-10-06 11:11:00 +02:00
eda72b2125 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m9s
2026-10-06 11:04:47 +02:00
9b2d49529e Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1m47s
2026-10-06 11:01:53 +02:00
7962a5367a Actualiser .gitea/workflows/build.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 1s
Removed auto run when pushing (debug)
2026-10-06 10:56:03 +02:00
cb1f648a31 Actualiser .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-10-06 10:55:31 +02:00
235a6f1c4e Ajouter .gitea/workflows/build_linux.yaml
Some checks failed
Build VulkanEngine / build (push) Failing after 0s
2026-10-06 10:46:04 +02:00
Alexandre
4e92afd550 re added the vk loader.
All checks were successful
Build VulkanEngine / build (push) Successful in 4m41s
i'm tired, i'll tackle it down tomorrow
2026-10-01 00:26:37 +02:00
Alexandre
5ce6f70155 Fixed a compilation error
Some checks failed
Build VulkanEngine / build (push) Failing after 2m24s
2026-10-01 00:21:24 +02:00
Alexandre
7e4aa7930c yapped on the readme 2026-10-01 00:18:54 +02:00
Alexandre
2f06209391 Removed the loader from appimage closure
Some checks failed
Build VulkanEngine / build (push) Failing after 2m27s
2026-10-01 00:14:04 +02:00
Alexandre
bb87c95da2 Tweaked again
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-10-01 00:13:09 +02:00
Alexandre
a09162d916 TWeaked some things
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-10-01 00:10:12 +02:00
Alexandre
98c4594885 Added a failsafe for list gpus
All checks were successful
Build VulkanEngine / build (push) Successful in 4m35s
2026-09-30 23:48:55 +02:00
Alexandre
3a80180add Tweaked the build
All checks were successful
Build VulkanEngine / build (push) Successful in 4m42s
2026-09-30 23:40:41 +02:00
Alexandre
8d83991d99 Yeah, it's an archive
All checks were successful
Build VulkanEngine / build (push) Successful in 4m32s
2026-09-30 23:33:20 +02:00
Alexandre
cfd92d7a87 Tweaked the build
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-09-30 23:29:05 +02:00
Alexandre
ede2e3f1f9 Changed the bundler
All checks were successful
Build VulkanEngine / build (push) Successful in 4m47s
2026-09-30 23:20:01 +02:00
Alexandre
c88340db29 Tweaked the action
All checks were successful
Build VulkanEngine / build (push) Successful in 13m28s
2026-09-30 22:59:37 +02:00
Alexandre
6ab1795eeb Tweaked the package
Some checks failed
Build VulkanEngine / build (push) Has been cancelled
2026-09-30 22:57:26 +02:00
Alexandre
69492d78ac Trying so bad 2026-09-30 22:31:32 +02:00
Alexandre
4b33ed8732 Adding a nix build 2026-09-30 22:09:58 +02:00
Alexandre
e4b44af05c First try at an action
All checks were successful
Build VulkanEngine / build (push) Successful in 3m36s
2026-09-30 21:59:48 +02:00
Alexandre
6df8188bb8 Oops, forgot to stage, see last commit message 2026-09-30 21:49:38 +02:00
Alexandre
817a4de020 Untracked .cache.
Also, updated some things and preparing for chapter 4
2026-09-30 21:49:22 +02:00
Alexandre
8f763d5e95 Modified imgui submodule source 2026-09-28 16:11:16 +02:00
Alexandre
0dfbf9011a Finished chapter 3 2026-09-28 15:51:31 +02:00
Alexandre
53a1a73bfc Tweaked the flake, changed some logs 2026-09-15 21:47:23 +02:00
Alexandre
1ad367d650 Removed the triangle and rectangle 2026-09-13 19:53:24 +02:00
Alexandre
f418ccabbc Added a depth image 2026-09-13 19:43:24 +02:00
Alexandre
86257df3e8 Updated gitignore 2026-09-13 19:42:54 +02:00
Alexandre
cc53d411ef Added a flake 2026-09-01 19:04:20 +02:00
Alexandre
3844f654cb Tweaked error messages in logs 2026-08-31 01:45:39 +02:00
Alexandre
b01fab5b9c Tweaked the gitignore 2026-08-31 01:42:02 +02:00
Alexandre
b25c3d8360 Tweaked help messages, and model loading 2026-08-31 01:40:02 +02:00
Alexandre
87e7db0c87 Added CLI arg and added a model 2026-08-25 23:40:47 +02:00
Alexandre
77ff2d7c0e Working on CLI args 2026-08-23 16:22:22 +02:00
Alexandre
f8b47fbdd4 Changed location of submodules 2026-08-22 12:11:30 +02:00
Alexandre
9236ada59a Added a rectangle, and started reworking logs 2026-08-18 03:13:38 +02:00
Alexandre
2603d12394 Added Viewport, now adding logs 2026-08-13 19:51:57 +02:00
Alexandre
46d150ac1d Commit before change, diverging from vkguide to add a viewport 2026-08-13 18:44:54 +02:00
Alexandre
fe7f7521d8 Added a triangle 2026-08-06 19:54:29 +02:00
Alexandre
c20c6928b1 Picked up vkguide again, switched from slang to glsl.
Created the triangle pipeline
2026-08-06 19:10:46 +02:00
28 changed files with 2953 additions and 302 deletions

View File

@ -11,3 +11,4 @@ CompileFlags:
- -DLOGGER_IMPL - -DLOGGER_IMPL
- -DSERVER_INIT_IMPL - -DSERVER_INIT_IMPL
- -DSERVER_IMPL - -DSERVER_IMPL
- -DLOADER_IMPL

4
.envrc
View File

@ -1,3 +1 @@
FLAKEPATH="/home/alex/Developer/nix/NixOSDots/dev-flakes" use flake
use flake ${FLAKEPATH}/vulkan

View File

@ -0,0 +1,54 @@
name: Build VulkanEngine
on:
push:
branches:
- vkguide
pull_request:
workflow_dispatch:
schedule:
- cron: "@weekly"
jobs:
build:
runs-on: ubuntu-22.04
container: git.alexdelcamp.fr/alexandre_1a/flake-actions:latest
steps:
- name: Checkout (avec submodules récursifs)
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: S'assurer que les flakes sont activés
run: |
mkdir -p ~/.config/nix
grep -q "experimental-features" ~/.config/nix/nix.conf 2>/dev/null || \
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf
- name: Build using nix
run: |
nix build .#engine
- name: Bundle
run: |
nix bundle --bundler github:ralismark/nix-appimage .#engine --out-link ./engine-bundle
- name: Upload des artefacts
if: success()
uses: actions/upload-artifact@v3
with:
name: vulkan-engine.zip
path: |
./engine-bundle
if-no-files-found: warn
archive: false
- name: Notify routine
if: always()
run: |
curl \
-H "Title: [Routine] VulkanEngine build" \
-d "Build finished (status: ${{ job.status }})" \
https://ntfy.alexdelcamp.fr/FlakeBuild

View File

@ -0,0 +1,272 @@
name: Build VulkanEngine
on:
push:
branches:
- vkguide
pull_request:
workflow_dispatch:
schedule:
- cron: "0 3 * * 1"
jobs:
# ---------------------------------------------------------------------------
# 1. Nix build: validates the flake build and produces the SPIR-V shaders
# (SPIR-V is OS independent, and slangc is not packaged in Debian).
# ---------------------------------------------------------------------------
nix:
runs-on: ubuntu-latest
container: git.alexdelcamp.fr/alexandre_1a/flake-actions:latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Configure
run: |
nix develop --command cmake -S . -B build \
-G Ninja \
-DCMAKE_BUILD_TYPE=Release
- name: Build
run: |
nix develop --command cmake --build build --parallel 2
- name: Upload shaders
uses: actions/upload-artifact@v4
with:
name: shaders
path: build/engine/shaders
- name: Notify progress
if: always()
run: |
curl \
-H "Title: [Routine] Shaders" \
-d "Build finished" \
https://ntfy.alexdelcamp.fr/FlakeBuild
# ---------------------------------------------------------------------------
# 2. Debian 12 builds: portable (static) and bundle (bin/ + lib/)
# Built on glibc 2.36 => runs on Debian 12 and anything newer.
# ---------------------------------------------------------------------------
debug:
needs: nix
runs-on: ubuntu-latest
container: debian:12
strategy:
fail-fast: false
steps:
# git + nodejs must exist before checkout (JS actions run in the container)
- name: Dependencies
run: |
apt-get update
apt-get install -y --no-install-recommends \
git ca-certificates nodejs curl \
build-essential cmake ninja-build pkg-config \
libwayland-dev libwayland-bin wayland-protocols libxkbcommon-dev \
libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Git safe directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Download shaders
uses: actions/download-artifact@v4
with:
name: shaders
path: prebuilt-shaders
- name: Configure
run: |
cmake -S . -B build -G Ninja \
--preset debug \
-DVULKANENGINE_FETCH_DEPS=ON \
-DVULKANENGINE_PORTABLE=ON \
-DVULKANENGINE_PREBUILT_SHADERS="$PWD/prebuilt-shaders"
- name: Build
run: cmake --build build --parallel 2
- name: Install
run: cmake --install build --prefix dist --strip
- name: Check binaries
shell: bash
run: |
set -euo pipefail
for b in dist/bin/engine dist/bin/server; do
echo "========== $b =========="
readelf -l "$b" | grep 'program interpreter'
readelf -d "$b" | grep -E 'RPATH|RUNPATH|NEEDED' || true
if strings "$b" | grep -q '/nix/store'; then
echo "ERROR: $b references /nix/store"; exit 1
fi
# The loader must come from volk (dlopen), never from NEEDED
if readelf -d "$b" | grep -q 'libvulkan'; then
echo "ERROR: $b links libvulkan directly"; exit 1
fi
if [ "PORTABLE" = "PORTABLE" ]; then
if readelf -d "$b" | grep -Eq 'libstdc\+\+|libgcc_s'; then
echo "ERROR: $b is not static for libstdc++/libgcc"; exit 1
fi
fi
max=$(objdump -T "$b" | grep -o 'GLIBC_[0-9.]*' | sed 's/GLIBC_//' | sort -uV | tail -1 || true)
echo "Highest GLIBC symbol: ${max:-none}"
if [ -n "$max" ] && [ "$(printf '%s\n%s\n' "$max" 2.36 | sort -V | tail -1)" != "2.36" ]; then
echo "ERROR: needs glibc $max (> 2.36)"; exit 1
fi
if ldd "$b" | grep 'not found'; then
echo "ERROR: unresolved libraries in $b"; exit 1
fi
done
# tar keeps permissions and symlinks; artifact zips do not
- name: Package
run: |
tar -C dist -czf VulkanEngine-DEBUG-linux-x86_64.tar.gz .
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: VulkanEngine-DEBUG-linux-x86_64
path: VulkanEngine-DEBUG-linux-x86_64.tar.gz
- name: Notify progress
if: failure()
run: |
curl \
-H "Title: [Routine] Engine-DEBUG build" \
-d "Build failed (nix: ${{ needs.nix.result }}, release: ${{ needs.debug.result }})" \
https://ntfy.alexdelcamp.fr/FlakeBuild
release:
needs: nix
runs-on: ubuntu-latest
container: debian:12
strategy:
fail-fast: false
matrix:
variant: [PORTABLE, BUNDLE]
steps:
# git + nodejs must exist before checkout (JS actions run in the container)
- name: Dependencies
run: |
apt-get update
apt-get install -y --no-install-recommends \
git ca-certificates nodejs curl \
build-essential cmake ninja-build pkg-config \
libwayland-dev libwayland-bin wayland-protocols libxkbcommon-dev \
libx11-dev libxrandr-dev libxinerama-dev libxcursor-dev libxi-dev
- name: Checkout
uses: actions/checkout@v4
with:
submodules: recursive
fetch-depth: 0
- name: Git safe directory
run: git config --global --add safe.directory "$GITHUB_WORKSPACE"
- name: Download shaders
uses: actions/download-artifact@v4
with:
name: shaders
path: prebuilt-shaders
- name: Configure
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_BUILD_TYPE=Release \
-DVULKANENGINE_FETCH_DEPS=ON \
-DVULKANENGINE_${{ matrix.variant }}=ON \
-DVULKANENGINE_PREBUILT_SHADERS="$PWD/prebuilt-shaders"
- name: Build
run: cmake --build build --parallel 2
- name: Install
run: cmake --install build --prefix dist --strip
- name: Check binaries
shell: bash
run: |
set -euo pipefail
for b in dist/bin/engine dist/bin/server; do
echo "========== $b =========="
readelf -l "$b" | grep 'program interpreter'
readelf -d "$b" | grep -E 'RPATH|RUNPATH|NEEDED' || true
if strings "$b" | grep -q '/nix/store'; then
echo "ERROR: $b references /nix/store"; exit 1
fi
# The loader must come from volk (dlopen), never from NEEDED
if readelf -d "$b" | grep -q 'libvulkan'; then
echo "ERROR: $b links libvulkan directly"; exit 1
fi
if [ "${{ matrix.variant }}" = "PORTABLE" ]; then
if readelf -d "$b" | grep -Eq 'libstdc\+\+|libgcc_s'; then
echo "ERROR: $b is not static for libstdc++/libgcc"; exit 1
fi
fi
max=$(objdump -T "$b" | grep -o 'GLIBC_[0-9.]*' | sed 's/GLIBC_//' | sort -uV | tail -1 || true)
echo "Highest GLIBC symbol: ${max:-none}"
if [ -n "$max" ] && [ "$(printf '%s\n%s\n' "$max" 2.36 | sort -V | tail -1)" != "2.36" ]; then
echo "ERROR: needs glibc $max (> 2.36)"; exit 1
fi
if ldd "$b" | grep 'not found'; then
echo "ERROR: unresolved libraries in $b"; exit 1
fi
done
if [ "${{ matrix.variant }}" = "BUNDLE" ]; then
echo "========== lib/ =========="
ls -la dist/lib
fi
# tar keeps permissions and symlinks; artifact zips do not
- name: Package
run: |
tar -C dist -czf VulkanEngine-${{ matrix.variant }}-linux-x86_64.tar.gz .
- name: Upload build
uses: actions/upload-artifact@v4
with:
name: VulkanEngine-${{ matrix.variant }}-linux-x86_64
path: VulkanEngine-${{ matrix.variant }}-linux-x86_64.tar.gz
- name: Notify progress
if: failure()
run: |
curl \
-H "Title: [Routine] Engine-${{ matrix.variant }} build" \
-d "Build failed (nix: ${{ needs.nix.result }}, release: ${{ needs.release.result }})" \
https://ntfy.alexdelcamp.fr/FlakeBuild
# ---------------------------------------------------------------------------
notify:
needs: [nix, release]
if: always()
runs-on: ubuntu-latest
steps:
- name: Notify routine
run: |
curl \
-H "Title: [Routine] VulkanEngine build" \
-d "Build finished (nix: ${{ needs.nix.result }}, release: ${{ needs.release.result }})" \
https://ntfy.alexdelcamp.fr/FlakeBuild

5
.gitignore vendored
View File

@ -37,6 +37,11 @@ Thumbs.db
# direnv # direnv
.direnv/ .direnv/
# cache
.cache
.cache/*
# Nix flakes # Nix flakes
result result
result-* result-*
.cache/*

11
.gitmodules vendored
View File

@ -1,3 +1,8 @@
[submodule "src/imgui"] [submodule "include/imgui"]
path = src/imgui path = include/imgui
url = https://github.com/ocornut/imgui.git url = https://git.alexdelcamp.fr/Alexandre_1a/imgui.git
branch = docking
[submodule "include/CLI11"]
path = include/CLI11
url = https://github.com/CLIUtils/CLI11.git

View File

@ -1,4 +1,4 @@
cmake_minimum_required (VERSION 3.29) cmake_minimum_required(VERSION 3.25) # Debian 12 ships 3.25
project(VulkanEngine) project(VulkanEngine)
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake") list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/CMake")
@ -9,10 +9,69 @@ include(FetchContent)
include(CheckIPOSupported) include(CheckIPOSupported)
check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT LTO_ERROR) check_ipo_supported(RESULT LTO_SUPPORTED OUTPUT LTO_ERROR)
# ---------------------------------------------------------------------------
# Build modes
# (default) Nix dev build, deps from the Nix shell
# FETCH_DEPS + PORTABLE Single directory, everything static except
# glibc (and the Vulkan loader, loaded via volk)
# FETCH_DEPS + BUNDLE bin/ + lib/, project libs shared in lib/,
# system libstdc++ / libc / loader are used
# ---------------------------------------------------------------------------
option(VULKANENGINE_PORTABLE
"Build a Linux binary without Nix-specific runtime paths (static libs)"
OFF
)
option(VULKANENGINE_BUNDLE
"Build a Linux bundle using libraries from the bundle directory"
OFF
)
option(VULKANENGINE_FETCH_DEPS
"Fetch dependencies with FetchContent instead of using system/Nix packages"
OFF
)
set(VULKANENGINE_PREBUILT_SHADERS "" CACHE PATH
"Directory containing precompiled .spv files (skips glslang/slangc)"
)
if(VULKANENGINE_PORTABLE AND VULKANENGINE_BUNDLE)
message(FATAL_ERROR "VULKANENGINE_PORTABLE and VULKANENGINE_BUNDLE are mutually exclusive")
endif()
if((VULKANENGINE_PORTABLE OR VULKANENGINE_BUNDLE) AND NOT VULKANENGINE_FETCH_DEPS)
message(FATAL_ERROR
"PORTABLE/BUNDLE builds need -DVULKANENGINE_FETCH_DEPS=ON "
"(Nix libraries must not leak into the result)")
endif()
set(CMAKE_EXPORT_COMPILE_COMMANDS ON) set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
# RPATH / runtime paths
if(VULKANENGINE_PORTABLE)
message(STATUS "VulkanEngine: PORTABLE build")
set(CMAKE_SKIP_RPATH TRUE)
elseif(VULKANENGINE_BUNDLE)
message(STATUS "VulkanEngine: BUNDLE build")
set(CMAKE_SKIP_BUILD_RPATH FALSE)
set(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE)
# Executables are installed in bin/
# Libraries are installed in lib/
set(CMAKE_INSTALL_RPATH "$ORIGIN/../lib")
set(CMAKE_INSTALL_RPATH_USE_LINK_PATH FALSE)
# Every shared lib we build ends up here, installed as-is into lib/
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib")
else()
message(STATUS "VulkanEngine: normal build")
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU") if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
find_program(GCC_AR NAMES gcc-ar REQUIRED) find_program(GCC_AR NAMES gcc-ar REQUIRED)
find_program(GCC_RANLIB NAMES gcc-ranlib REQUIRED) find_program(GCC_RANLIB NAMES gcc-ranlib REQUIRED)
@ -20,19 +79,103 @@ if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
set(CMAKE_RANLIB "${GCC_RANLIB}") set(CMAKE_RANLIB "${GCC_RANLIB}")
endif() endif()
# Find all package dependencies # ---------------------------------------------------------------------------
# Dependencies
# ---------------------------------------------------------------------------
# Same in every mode: no link-time dependency on libvulkan, all Vulkan
# functions come from volk (otherwise vk*KHR aliases are undefined at link).
set(ENGINE_EXTRA_DEFINITIONS
GLFW_INCLUDE_NONE
VK_NO_PROTOTYPES
VMA_STATIC_VULKAN_FUNCTIONS=0
VMA_DYNAMIC_VULKAN_FUNCTIONS=1
)
if(VULKANENGINE_FETCH_DEPS)
# Portable = static libs, bundle = shared libs (in lib/)
if(VULKANENGINE_BUNDLE)
set(BUILD_SHARED_LIBS ON)
else()
set(BUILD_SHARED_LIBS OFF)
endif()
set(CMAKE_POSITION_INDEPENDENT_CODE ON)
set(VULKAN_HEADERS_ENABLE_MODULE OFF CACHE BOOL "" FORCE)
set(VULKAN_HEADERS_ENABLE_TESTS OFF CACHE BOOL "" FORCE)
set(VULKAN_HEADERS_ENABLE_INSTALL OFF CACHE BOOL "" FORCE)
set(VOLK_PULL_IN_VULKAN OFF CACHE BOOL "" FORCE)
set(VOLK_INSTALL OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_INSTALL OFF CACHE BOOL "" FORCE)
set(FMT_INSTALL OFF CACHE BOOL "" FORCE)
set(FMT_TEST OFF CACHE BOOL "" FORCE)
set(SIMDJSON_DEVELOPER_MODE OFF CACHE BOOL "" FORCE)
set(CLI11_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(CLI11_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
set(GLM_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLM_BUILD_LIBRARY OFF CACHE BOOL "" FORCE)
# Keep these versions in sync with your nixpkgs (check the tags exist)
FetchContent_Declare(VulkanHeaders
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Headers.git
GIT_TAG v1.4.309)
# vulkan/vk_enum_string_helper.h lives here, not in Vulkan-Headers.
# SOURCE_SUBDIR points to a nonexistent dir so MakeAvailable only downloads
# (we use the checked-in header, no need to run its CMake).
FetchContent_Declare(VulkanUtilityLibraries
GIT_REPOSITORY https://github.com/KhronosGroup/Vulkan-Utility-Libraries.git
GIT_TAG v1.4.309
SOURCE_SUBDIR _no_cmake)
FetchContent_Declare(volk
GIT_REPOSITORY https://github.com/zeux/volk.git
GIT_TAG 1.4.304)
FetchContent_Declare(VMA
GIT_REPOSITORY https://github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator.git
GIT_TAG v3.2.1)
FetchContent_Declare(glfw
GIT_REPOSITORY https://github.com/glfw/glfw.git
GIT_TAG 3.4)
FetchContent_Declare(vk-bootstrap
GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap.git
GIT_TAG v1.4.365)
FetchContent_Declare(fmt
GIT_REPOSITORY https://github.com/fmtlib/fmt.git
GIT_TAG 11.0.2)
FetchContent_Declare(CLI11
GIT_REPOSITORY https://github.com/CLIUtils/CLI11.git
GIT_TAG v2.4.2)
FetchContent_Declare(glm
GIT_REPOSITORY https://github.com/g-truc/glm.git
GIT_TAG 1.0.1)
FetchContent_Declare(simdjson
GIT_REPOSITORY https://github.com/simdjson/simdjson.git
GIT_TAG v3.10.1)
# Vulkan headers first: vk-bootstrap and volk pick up Vulkan::Headers
FetchContent_MakeAvailable(VulkanHeaders VulkanUtilityLibraries)
FetchContent_MakeAvailable(volk VMA glfw vk-bootstrap fmt CLI11 glm simdjson)
target_link_libraries(volk PUBLIC Vulkan::Headers)
add_library(vk_utility_headers INTERFACE)
target_include_directories(vk_utility_headers SYSTEM INTERFACE
${vulkanutilitylibraries_SOURCE_DIR}/include)
target_link_libraries(vk_utility_headers INTERFACE Vulkan::Headers)
else()
# Nix path
find_package( volk CONFIG REQUIRED )
find_package( glfw3 REQUIRED ) find_package( glfw3 REQUIRED )
find_package( glm REQUIRED ) find_package( glm REQUIRED )
find_package( VulkanMemoryAllocator CONFIG REQUIRED ) find_package( VulkanMemoryAllocator CONFIG REQUIRED )
find_package( fmt REQUIRED ) find_package( CLI11 REQUIRED )
# Shader compilers find_package( simdjson REQUIRED )
add_executable (glslang::validator IMPORTED) endif()
find_program (GLSLANG_VALIDATOR "glslangValidator" HINTS $ENV{VULKAN_SDK}/bin REQUIRED)
set_property (TARGET glslang::validator PROPERTY IMPORTED_LOCATION "${GLSLANG_VALIDATOR}")
find_program(SLANGC_EXECUTABLE slangc HINTS $ENV{VULKAN_SDK}/bin REQUIRED)
# fastgltf because it's not in nixpkgs
# fastgltf because it's not in nixpkgs (declared after the switch above so it
# inherits BUILD_SHARED_LIBS)
FetchContent_Declare( FetchContent_Declare(
fastgltf fastgltf
GIT_REPOSITORY https://github.com/spnda/fastgltf.git GIT_REPOSITORY https://github.com/spnda/fastgltf.git
@ -40,13 +183,26 @@ FetchContent_Declare(
) )
FetchContent_MakeAvailable(fastgltf) FetchContent_MakeAvailable(fastgltf)
# vk-bootstrap because CMAKE can't find it on NixOS # ---------------------------------------------------------------------------
FetchContent_Declare( # Shader compilers (not needed when precompiled shaders are provided)
vk-bootstrap # ---------------------------------------------------------------------------
GIT_REPOSITORY https://github.com/charles-lunarg/vk-bootstrap.git if(NOT VULKANENGINE_PREBUILT_SHADERS)
GIT_TAG v1.3.295 add_executable (glslang::validator IMPORTED)
find_program (
GLSLANG_VALIDATOR
"glslangValidator"
HINTS $ENV{VULKAN_SDK}/bin
REQUIRED
) )
FetchContent_MakeAvailable(vk-bootstrap)
set_property (
TARGET glslang::validator
PROPERTY IMPORTED_LOCATION "${GLSLANG_VALIDATOR}"
)
find_program(SLANGC_EXECUTABLE slangc HINTS $ENV{VULKAN_SDK}/bin REQUIRED)
endif()
# Helper functions to build shaders # Helper functions to build shaders
function(addGlslShader SOURCE OUTPUT_DIR) function(addGlslShader SOURCE OUTPUT_DIR)
@ -91,21 +247,39 @@ endfunction()
# A function to automate executables aditions # A function to automate executables aditions
function ( addBinary BINARY_NAME ) function ( addBinary BINARY_NAME )
cmake_parse_arguments ( BINARY "IMGUI;LICENSE" "SOURCE" "SHADERS;SLANG_SHADERS;LIBS;TEXTURES;MODELS" ${ARGN} ) cmake_parse_arguments ( BINARY "IMGUI;LICENSE" "SOURCE" "SHADERS;SLANG_SHADERS;SLANG_ENTRIES;LIBS;TEXTURES;MODELS" ${ARGN} )
if (DEFINED BINARY_SOURCE) if (DEFINED BINARY_SOURCE)
add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp ) add_executable ( ${BINARY_NAME} src/${BINARY_SOURCE}.cpp )
endif() endif()
target_include_directories( ${BINARY_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src ) target_include_directories( ${BINARY_NAME} PRIVATE ${CMAKE_SOURCE_DIR}/src )
# Sets the output dir to have clear separation between binaries # Sets the output dir to have clear separation between binaries
set_target_properties ( ${BINARY_NAME} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/${BINARY_NAME} ) set_target_properties (
set_target_properties ( ${BINARY_NAME} PROPERTIES CXX_STANDARD 20 ) # Uses C++20 ${BINARY_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY
${CMAKE_BINARY_DIR}/${BINARY_NAME}
CXX_STANDARD
20 # C++ 20
CXX_STANDARD_REQUIRED
ON
CXX_EXTENSIONS
OFF
CXX_SCAN_FOR_MODULES
OFF
)
# Sets per binary LTO # Sets per binary LTO
if(LTO_SUPPORTED AND CMAKE_BUILD_TYPE STREQUAL "Release") if(LTO_SUPPORTED AND CMAKE_BUILD_TYPE STREQUAL "Release")
set_target_properties(${BINARY_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE) set_target_properties(${BINARY_NAME} PROPERTIES INTERPROCEDURAL_OPTIMIZATION TRUE)
message("Enabled LTO") message("Enabled LTO")
endif() endif()
set_target_properties(${BINARY_NAME} PROPERTIES CXX_SCAN_FOR_MODULES OFF)
# Portable: libstdc++/libgcc statically linked so the binary does not depend
# on the host's version. NOT done for bundle: the shared libs in lib/ use the
# system libstdc++, and mixing two copies in one process is asking for trouble.
if(VULKANENGINE_PORTABLE)
target_link_options(${BINARY_NAME} PRIVATE -static-libstdc++ -static-libgcc)
endif()
# Define VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS to treat VK_ERROR_OUT_OF_DATE_KHR as a success code # Define VULKAN_HPP_HANDLE_ERROR_OUT_OF_DATE_AS_SUCCESS to treat VK_ERROR_OUT_OF_DATE_KHR as a success code
target_compile_definitions ( target_compile_definitions (
@ -115,25 +289,33 @@ function ( addBinary BINARY_NAME )
$<$<CONFIG:Debug>:DEBUG> # So CMAKE expose a #define DEBUG for debug builds $<$<CONFIG:Debug>:DEBUG> # So CMAKE expose a #define DEBUG for debug builds
# Exposes versions # Exposes versions
BUILD_ID="${ENGINE_VERSION}" BUILD_ID="${ENGINE_VERSION}"
${ENGINE_EXTRA_DEFINITIONS}
) )
if(BINARY_IMGUI) if(BINARY_IMGUI)
target_include_directories(${BINARY_NAME} PRIVATE target_include_directories(${BINARY_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/src/imgui ${CMAKE_SOURCE_DIR}/include/imgui
${CMAKE_SOURCE_DIR}/src/imgui/backends ${CMAKE_SOURCE_DIR}/include/imgui/backends
) )
target_sources(${BINARY_NAME} PRIVATE target_sources(${BINARY_NAME} PRIVATE
${CMAKE_SOURCE_DIR}/src/imgui/imgui.cpp ${CMAKE_SOURCE_DIR}/include/imgui/imgui.cpp
${CMAKE_SOURCE_DIR}/src/imgui/imgui_draw.cpp ${CMAKE_SOURCE_DIR}/include/imgui/imgui_draw.cpp
${CMAKE_SOURCE_DIR}/src/imgui/imgui_tables.cpp ${CMAKE_SOURCE_DIR}/include/imgui/imgui_tables.cpp
${CMAKE_SOURCE_DIR}/src/imgui/imgui_widgets.cpp ${CMAKE_SOURCE_DIR}/include/imgui/imgui_widgets.cpp
${CMAKE_SOURCE_DIR}/src/imgui/imgui_demo.cpp ${CMAKE_SOURCE_DIR}/include/imgui/imgui_demo.cpp
#${CMAKE_SOURCE_DIR}/include/imgui/imgui_memory_editor.h
${CMAKE_SOURCE_DIR}/src/imgui/backends/imgui_impl_glfw.cpp ${CMAKE_SOURCE_DIR}/include/imgui/backends/imgui_impl_glfw.cpp
${CMAKE_SOURCE_DIR}/src/imgui/backends/imgui_impl_vulkan.cpp ${CMAKE_SOURCE_DIR}/include/imgui/backends/imgui_impl_vulkan.cpp
) )
# imgui's Vulkan backend must use volk since there is no linked loader
target_compile_definitions(${BINARY_NAME} PRIVATE IMGUI_IMPL_VULKAN_USE_VOLK)
endif() endif()
if(BINARY_LICENSE) if(BINARY_LICENSE)
file(COPY ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/${BINARY_NAME}) file(COPY ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION ${CMAKE_BINARY_DIR}/${BINARY_NAME})
endif() endif()
@ -141,6 +323,15 @@ function ( addBinary BINARY_NAME )
if(DEFINED BINARY_SHADERS) if(DEFINED BINARY_SHADERS)
set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${BINARY_NAME}/shaders) set(SHADER_OUTPUT_DIR ${CMAKE_BINARY_DIR}/${BINARY_NAME}/shaders)
if(VULKANENGINE_PREBUILT_SHADERS)
# Copy the .spv produced by the Nix job instead of compiling them
file(GLOB PREBUILT_SPV CONFIGURE_DEPENDS "${VULKANENGINE_PREBUILT_SHADERS}/*.spv")
if(NOT PREBUILT_SPV)
message(FATAL_ERROR "No .spv found in ${VULKANENGINE_PREBUILT_SHADERS}")
endif()
file(COPY ${PREBUILT_SPV} DESTINATION ${SHADER_OUTPUT_DIR})
else()
set(ALL_SPV_FILES "") set(ALL_SPV_FILES "")
set(EXPANDED_SHADERS "") set(EXPANDED_SHADERS "")
@ -170,9 +361,10 @@ function ( addBinary BINARY_NAME )
add_custom_target(shaders_${BINARY_NAME} DEPENDS ${ALL_SPV_FILES}) add_custom_target(shaders_${BINARY_NAME} DEPENDS ${ALL_SPV_FILES})
add_dependencies(${BINARY_NAME} shaders_${BINARY_NAME}) add_dependencies(${BINARY_NAME} shaders_${BINARY_NAME})
endif() endif()
endif()
if (DEFINED BINARY_LIBS) if (DEFINED BINARY_LIBS)
target_link_libraries ( ${BINARY_NAME} ${BINARY_LIBS} ) target_link_libraries ( ${BINARY_NAME} PRIVATE ${BINARY_LIBS} )
endif() endif()
if (DEFINED BINARY_MODELS) # Adds the 3D models in the binary folder if (DEFINED BINARY_MODELS) # Adds the 3D models in the binary folder
@ -205,23 +397,73 @@ function ( addBinary BINARY_NAME )
endfunction() endfunction()
# Scan the shader folder # ---------------------------------------------------------------------------
file(GLOB SHADER_SOURCES CONFIGURE_DEPENDS "shaders/*") # Binaries
# ---------------------------------------------------------------------------
list(
APPEND
lib_list
# Libs used
glfw
fmt
vk-bootstrap
CLI11::CLI11
fastgltf
)
# Adds the main binary if(VULKANENGINE_FETCH_DEPS)
# No libvulkan at link time: volk loads libvulkan.so.1 at runtime.
# Remove what your code does not use (simdjson, glm...).
list(APPEND lib_list
volk
Vulkan::Headers
vk_utility_headers
GPUOpen::VulkanMemoryAllocator
glm::glm-header-only
simdjson::simdjson
)
else()
# Nix: volk comes from nixpkgs (vulkan-volk); libvulkan is NOT linked
list(APPEND lib_list volk::volk)
endif()
addBinary ( addBinary (
engine engine
SOURCE Engine/main SOURCE Engine/main
# Flags
SHADERS ${SHADER_SOURCES}
SHADERS
LIBS glfw fmt vk-bootstrap vulkan
IMGUI IMGUI
LICENSE LICENSE
SHADERS shaders/*
MODELS *
LIBS ${lib_list}
) )
addBinary ( addBinary (
server server
SOURCE Server/main SOURCE Server/main
) )
# ---------------------------------------------------------------------------
# Install (used for portable / bundle packaging)
# dist/bin/{engine,server,shaders,models,textures}
# dist/lib/*.so* (bundle only)
# dist/LICENSE
# Never bundled: libc, libstdc++, libvulkan, GL, X11, Wayland.
# ---------------------------------------------------------------------------
install(TARGETS engine server RUNTIME DESTINATION bin)
install(DIRECTORY ${CMAKE_BINARY_DIR}/engine/shaders DESTINATION bin OPTIONAL)
install(DIRECTORY ${CMAKE_BINARY_DIR}/engine/models DESTINATION bin OPTIONAL)
install(DIRECTORY ${CMAKE_BINARY_DIR}/engine/textures DESTINATION bin OPTIONAL)
install(FILES ${CMAKE_SOURCE_DIR}/LICENSE DESTINATION .)
if(VULKANENGINE_BUNDLE)
# Every shared lib built from fetched deps (glfw, fmt, fastgltf and its own
# simdjson, ...) with its symlinks. libstdc++ etc. are not built here.
install(DIRECTORY ${CMAKE_LIBRARY_OUTPUT_DIRECTORY}/
DESTINATION lib
USE_SOURCE_PERMISSIONS
FILES_MATCHING PATTERN "*.so*"
)
endif()

View File

@ -5,3 +5,20 @@ Might expending it later into a game or engine.
Based from [vkguide](https://vkguide.dev/) Based from [vkguide](https://vkguide.dev/)
This has a very different philosophy than the main [Khronos Vulkan Tutorial](https://docs.vulkan.org/tutorial/latest/00_Introduction.html) This has a very different philosophy than the main [Khronos Vulkan Tutorial](https://docs.vulkan.org/tutorial/latest/00_Introduction.html)
## Install
You can build it yourself, using two methods:
1- Use a devenv, and cmake
2- Use nix build
Or you can grab an artefact from the actions tab (currently broken).
## Usage
All runtime documentation is included in the program, just launch it witout any arguments, or with the `-h` flag to see how to use it.
## Known bugs
Currently, when opening a new build, the imgui layout is not done, you need to dock everything yourself, only at the first launch (after that, the layout is saved in `imgui.ini`)
You also need to launch the executable in the same folder as the assets (shaders, models, textures).
All of these "bugs" are planned to be fixed.

11
ROADMAP.md Normal file
View File

@ -0,0 +1,11 @@
# Roadmap
Finish vkguide.dev
Rewrite some part, for structure purposes
Configure offscreen rendering for imgui (docked viewport)
Separate tooling and core, for shipping
- #ifdef DEBUG for tools
- #ifdef NDEBUG for release

BIN
assets/models/basicmesh.glb Normal file

Binary file not shown.

58
flake.lock generated Normal file
View File

@ -0,0 +1,58 @@
{
"nodes": {
"flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": {
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1791366222,
"narHash": "sha256-/4ezBOv6aldGab7qTb6ls3SDpgzG8kuuSqEAA9zEZ8E=",
"rev": "39ad350a0602fa0a58a544344e3e9187526ea45c",
"type": "tarball",
"url": "https://releases.nixos.org/nixpkgs/nixpkgs-26.11pre1087089.39ad350a0602/nixexprs.tar.zst"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
}
},
"systems": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
"version": 7
}

114
flake.nix Normal file
View File

@ -0,0 +1,114 @@
{
description = "VulkanEngine development environment";
inputs = {
nixpkgs.url = "nixpkgs";
flake-utils.url = "github:numtide/flake-utils";
};
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem (system:
let
pkgs = import nixpkgs {
inherit system;
config.allowUnfree = true;
};
vulkanPackages = with pkgs; [
vulkan-headers
vulkan-loader
vulkan-validation-layers
vulkan-tools
vulkan-utility-libraries
vulkan-memory-allocator
vulkan-volk
vk-bootstrap
];
developmentPackages = with pkgs; [
# Shaders
shader-slang
glslang
# Vulkan
vulkan-headers
vulkan-loader
vulkan-validation-layers
vulkan-tools
vulkan-utility-libraries
vulkan-memory-allocator
vulkan-volk
vk-bootstrap
# Windowing
glfw3
wayland
wayland-protocols
wayland-scanner
libxkbcommon
# Audio
libpulseaudio
libpulseaudio.dev
# Libraries
fmt
cli11
simdjson
glm
nlohmann_json
tinyobjloader
tinygltf
stb
# Build
cmake
ninja
pkg-config
# Debug
gdb
renderdoc
];
in {
devShells.default = pkgs.mkShell {
name = "vulkan-engine";
hardeningDisable = [
"fortify"
];
packages = developmentPackages;
VK_LAYER_PATH =
"${pkgs.vulkan-validation-layers}/share/vulkan/explicit_layer.d";
VULKAN_SDK =
"${pkgs.vulkan-validation-layers}";
shellHook = ''
export LD_LIBRARY_PATH="${pkgs.lib.makeLibraryPath [
pkgs.vulkan-loader
pkgs.wayland
pkgs.libxkbcommon
]}"
echo "VulkanEngine development environment"
echo "CMake: $(cmake --version | head -n1)"
echo "Ninja: $(ninja --version)"
echo "GCC: $(g++ --version | head -n1)"
echo "GLSLang: $(glslangValidator --version | head -n1)"
echo "Slang: $(slangc -v | head -n1)"
unset SOURCE_DATE_EPOCH
'';
};
packages.engine =
pkgs.callPackage ./package.nix {};
packages.default =
self.packages.${system}.engine;
}
);
}

1
include/CLI11 Submodule

@ -0,0 +1 @@
Subproject commit c1cfe00d2f3d862aecfe6e69ec810414d5f4c906

1
include/imgui Submodule

@ -0,0 +1 @@
Subproject commit d7cce3ad5070bbdbbd7a39335c0c1e90071211d0

117
package.nix Normal file
View File

@ -0,0 +1,117 @@
{ lib
, stdenv
, fetchFromGitHub
, fetchgit
, cmake
, ninja
, pkg-config
, glfw3
, glm
, vulkan-headers
, vulkan-loader
, vulkan-volk
, vulkan-utility-libraries
, vulkan-memory-allocator
, vk-bootstrap
, fmt
, cli11
, glslang
, shader-slang
, simdjson
, patchelf
}:
let
fs = lib.fileset;
fastgltf = fetchFromGitHub {
owner = "spnda";
repo = "fastgltf";
rev = "v0.8.0";
hash = "sha256-nPkVMrve1+04XRpSswBqjlSurliCFBRxR8Zxy4xZ5pE=";
};
imgui = fetchgit {
url = "https://git.alexdelcamp.fr/Alexandre_1a/imgui.git";
rev = "d7cce3ad5070bbdbbd7a39335c0c1e90071211d0";
hash = "sha256-2v085YFc17aj96YlOc4Fp8sJUHUmjRU8X54FnuqKrgc=";
};
in
stdenv.mkDerivation {
pname = "vulkan-engine";
version = "1.1.0";
src = ./.;
postUnpack = ''
# include/ peut ne pas exister du tout dans la copie flake
# (cas de figure ici), donc on le crée.
mkdir -p $sourceRoot/include
# On remplace les dossiers vides (ou absents) par les vraies sources
rm -rf $sourceRoot/include/imgui $sourceRoot/include/CLI11
cp -r ${imgui} $sourceRoot/include/imgui
# Autorise le write sur l'arbre : CMake va générer des fichiers
chmod -R u+w $sourceRoot
'';
nativeBuildInputs = [
cmake
ninja
pkg-config
glslang
shader-slang
];
buildInputs = [
glfw3
glm
vulkan-headers
vulkan-volk
vulkan-loader
vulkan-utility-libraries
vk-bootstrap
vulkan-memory-allocator
fmt
cli11
simdjson
];
cmakeFlags = [
"-DCMAKE_BUILD_TYPE=Release"
"-DCMAKE_EXPORT_COMPILE_COMMANDS=ON"
"-DFETCHCONTENT_SOURCE_DIR_FASTGLTF=${fastgltf}"
"-DFETCHCONTENT_FULLY_DISCONNECTED=ON"
];
postFixup = ''
patchelf --add-rpath ${lib.makeLibraryPath [ vulkan-loader ]} $out/bin/engine
'';
installPhase = ''
runHook preInstall
mkdir -p $out/bin
cp engine/engine $out/bin/engine
cp server/server $out/bin/server
# Copier les shaders compilés où qu'ils soient
if [ -d engine/shaders ]; then
cp -r engine/shaders $out/bin/shaders
elif [ -d $sourceRoot/engine/shaders ]; then
# fallback : sources, à compiler ? normalement non
cp -r $sourceRoot/engine/shaders $out/bin/shaders
else
echo "ERREUR : aucun dossier shaders trouvé" >&2
find . -name "*.spv" >&2
exit 1
fi
[ -d engine/models ] && cp -r engine/models $out/bin/models
[ -d engine/textures ] && cp -r engine/textures $out/bin/textures
[ -f engine/LICENSE ] && cp engine/LICENSE $out/bin/LICENSE
runHook postInstall
'';
meta.mainProgram = "engine";
}

View File

@ -1,30 +0,0 @@
static float2 positions[3] = float2[](
float2(0.0, -0.5),
float2(0.5, 0.5),
float2(-0.5, 0.5)
);
static float3 colors[3] = float3[] (
float3(1.0, 0.0, 0.0),
float3(0.0, 1.0, 0.0),
float3(0.0, 0.0, 1.0)
);
struct VertexOutput {
float3 color;
float4 sv_position : SV_Position;
};
[shader("vertex")]
VertexOutput vertMain(uint vid : SV_VertexID) {
VertexOutput output;
output.sv_position = float4(positions[vid], 0.0, 1.0);
output.color = colors[vid];
return output;
}
[shader("fragment")]
float4 fragMain(VertexOutput inVert) : SV_Target {
float3 color = inVert.color;
return float4(color, 1.0);
}

View File

@ -0,0 +1,13 @@
#version 450
//shader input
layout(location = 0) in vec3 inColor;
//output write
layout(location = 0) out vec4 outFragColor;
void main()
{
//return red
outFragColor = vec4(inColor, 1.0f);
}

View File

@ -0,0 +1,36 @@
#version 450
#extension GL_EXT_buffer_reference : require
layout(location = 0) out vec3 outColor;
layout(location = 1) out vec2 outUV;
struct Vertex {
vec3 position;
float uv_x;
vec3 normal;
float uv_y;
vec4 color;
};
layout(buffer_reference, std430) readonly buffer VertexBuffer {
Vertex vertices[];
};
//push constants block
layout(push_constant) uniform constants
{
mat4 render_matrix;
VertexBuffer vertexBuffer;
} PushConstants;
void main()
{
//load vertex data from device adress
Vertex v = PushConstants.vertexBuffer.vertices[gl_VertexIndex];
//output data
gl_Position = PushConstants.render_matrix * vec4(v.position, 1.0f);
outColor = v.color.xyz;
outUV.x = v.uv_x;
outUV.y = v.uv_y;
}

View File

@ -0,0 +1,24 @@
#version 450
layout (location = 0) out vec3 outColor;
void main()
{
//const array of positions for the triangle
const vec3 positions[3] = vec3[3](
vec3(1.f,1.f, 0.0f),
vec3(-1.f,1.f, 0.0f),
vec3(0.f,-1.f, 0.0f)
);
//const array of colors for the triangle
const vec3 colors[3] = vec3[3](
vec3(1.0f, 0.0f, 0.0f), //red
vec3(0.0f, 1.0f, 0.0f), //green
vec3(00.f, 0.0f, 1.0f) //blue
);
//output the position of each vertex
gl_Position = vec4(positions[gl_VertexIndex], 1.0f);
outColor = colors[gl_VertexIndex];
}

View File

@ -1,8 +1,31 @@
/*
Todo:
The timestamp is not in localtime,
fix or disclaim
*/
#ifndef LOGGER_H #ifndef LOGGER_H
#define LOGGER_H #define LOGGER_H
// Custom includes // Custom includes
// Enums
enum class LogModule {
ENGINE,
RENDERER,
GLFW,
CLEANUP
};
enum class LogLevel {
EDEBUG,
EINIT, // Initialization related
EINFO, // General infos
EWARN,
EERROR,
EFATAL
};
class NetLogger { class NetLogger {
public: public:
struct Server{ struct Server{
@ -17,7 +40,79 @@ class NetLogger {
void logNetAsync(); // Todo void logNetAsync(); // Todo
private: private:
};
class Logger {
public:
// Members
std::string logBuffer; // Log is empty by default
std::vector<std::string_view> lines;
// Functions
template<typename... Args>
void logDisk(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
); // Logs to a file on disk
// Overload
void logDisk(std::string_view message);
template<typename... Args>
void logRAM(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
); // Logs to ram (ImGUI)
template<typename... Args>
void logConsole(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
); // Logs to the console (crashes, etc...)
template<typename... Args>
void logAll(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
); // Logs using all of the above, RAM then console and finally disk, maybe multithread (?)
template<typename... Args>
void logImportant(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
); // Logs to console and file, in cases of crashes or errors
template<typename... Args>
void logFatal(
LogModule module,
std::string_view message,
Args&&... args
); // Logs to console and file, then abort -> Core dump
// Utils functions
void merge(std::string_view source); // Merges a source dumped logs into this
void logSeparator();
void clear();
private:
// Helper functions
static std::string_view moduleToString(LogModule m);
static std::string_view levelToString(LogLevel l);
inline std::string formatTimestamp(
std::chrono::system_clock::time_point tp
);
}; };
#endif // End of header #endif // End of header
@ -29,12 +124,271 @@ class NetLogger {
// Implementation // Implementation
// Includes // Includes
#include <httplib.h> // Todo : add it in the flake //#include <httplib.h> // Todo : add it in the flake
#include <iostream>
#include <fstream>
#include <chrono>
/*
void NetLogger::initNetLogger(Server server) { void NetLogger::initNetLogger(Server server) {
httplib::Client cli(server.url) httplib::Client cli(server.url)
// Todo : add error handling // Todo : add error handling
} }
*/
template<typename... Args>
void Logger::logRAM(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
) {
auto now { std::chrono::system_clock::now() };
auto timestamp = formatTimestamp(now);
auto start = logBuffer.size();
fmt::format_to(
std::back_inserter(logBuffer),
"[{}] ",
timestamp
);
fmt::format_to(
std::back_inserter(logBuffer),
"[{}:{}] ",
moduleToString(module),
levelToString(level)
);
fmt::format_to(
std::back_inserter(logBuffer),
fmt::runtime(message),
std::forward<Args>(args)...
);
logBuffer.push_back('\n');
auto end = logBuffer.size();
lines.emplace_back(logBuffer.data() + start, end - start);
}
template<typename... Args>
void Logger::logConsole(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
) {
std::string tempBuffer;
auto now = std::chrono::system_clock::now();
auto timestamp = formatTimestamp(now);
fmt::format_to(
std::back_inserter(tempBuffer),
"[{}] ",
timestamp
);
fmt::format_to(
std::back_inserter(tempBuffer),
"[{}:{}] ",
moduleToString(module),
levelToString(level)
);
fmt::format_to(
std::back_inserter(tempBuffer),
fmt::runtime(message),
std::forward<Args>(args)...
);
std::cout.write(tempBuffer.data(), tempBuffer.size());
std::cout.put('\n');
}
template<typename... Args>
void Logger::logDisk(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
) {
// Open the logfile
std::ofstream logFile ("log.txt", std::ios::out | std::ios::app);
if (!logFile.good()) {
throw std::runtime_error("Failed to open logfile !");
}
// Create a temporary buffer
std::string tempBuffer;
auto now = std::chrono::system_clock::now();
auto timestamp = formatTimestamp(now);
fmt::format_to(
std::back_inserter(tempBuffer),
"[{}] ",
timestamp
);
fmt::format_to(
std::back_inserter(tempBuffer),
"[{}:{}] ",
moduleToString(module),
levelToString(level)
);
fmt::format_to(
std::back_inserter(tempBuffer),
fmt::runtime(message),
std::forward<Args>(args)...
);
logFile << tempBuffer << '\n';
logFile.close();
}
// Overload to inject a message
void Logger::logDisk(std::string_view message) {
std::ofstream logFile ("log.txt", std::ios::out | std::ios::app);
if (!logFile.good()) {
throw std::runtime_error("Failed to open logfile !");
}
logFile << message << '\n';
logFile.close();
}
template<typename... Args>
void Logger::logAll(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
) {
// Logs to all targets !
logRAM(
module,
level,
message,
args...
);
logConsole(
module,
level,
message,
args...
);
logDisk(
module,
level,
message,
args...
);
}
template<typename... Args>
void Logger::logImportant(
LogModule module,
LogLevel level,
std::string_view message,
Args&&... args
) {
logDisk(
module,
level,
message,
args...
);
logConsole(
module,
level,
message,
args...
);
}
template<typename... Args>
void Logger::logFatal(
LogModule module,
std::string_view message,
Args&&... args
) {
// Separator
logDisk("================================== CRASH LOGS ==================================");
logDisk(
module,
LogLevel::EFATAL,
message,
args...
);
logConsole(
module,
LogLevel::EFATAL,
message,
args...
);
logSeparator();
std::abort();
}
void Logger::merge(std::string_view source) {
/*
This merges a dumped logger into this one
Assumes the other logger is already formated.
This allows to add arbitrary strings into the logs
*/
logBuffer += source;
}
void Logger::logSeparator() {
logDisk("================================================================================");
}
void Logger::clear() {
logBuffer.clear();
}
std::string_view Logger::moduleToString(LogModule m) {
using enum LogModule;
switch (m) {
case ENGINE: return "Engine";
case RENDERER: return "Renderer";
case GLFW: return "GLFW";
case CLEANUP: return "CLEANUP";
default: return "Unkown";
}
}
std::string_view Logger::levelToString(LogLevel l) {
using enum LogLevel;
switch (l) {
case EDEBUG: return "Debug";
case EINFO: return "Info";
case EINIT: return "Init";
case EWARN: return "Warn";
case EERROR: return "Error";
case EFATAL: return "Fatal";
default: return "???";
}
}
std::string Logger::formatTimestamp(
std::chrono::system_clock::time_point tp
) {
std::time_t t = std::chrono::system_clock::to_time_t(tp);
std::tm tm{};
localtime_r(&t, &tm);
return fmt::format("{:%Y-%m-%d %H:%M}", tm);
}
#endif #endif
#endif #endif

View File

@ -12,19 +12,25 @@
#include <chrono> #include <chrono>
#include <thread> #include <thread>
#include <fmt/base.h> #include <fmt/base.h>
#include <fmt/format.h>
#include <fmt/chrono.h>
#include <stdexcept> #include <stdexcept>
#include <cstdint> #include <cstdint>
#include <vulkan/vulkan.h> #include <volk.h>
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
#include <vulkan/vk_enum_string_helper.h> #include <vulkan/vk_enum_string_helper.h>
#include <vk_mem_alloc.h> #include <vk_mem_alloc.h>
#define GLFW_INCLUDE_VULKAN //#define GLFW_INCLUDE_NONE
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#define GLM_ENABLE_EXPERIMENTAL
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#define GLM_FORCE_RADIANS
#include <glm/mat4x4.hpp> #include <glm/mat4x4.hpp>
#include <glm/vec4.hpp> #include <glm/vec4.hpp>
#include <glm/gtx/transform.hpp>
// Custom headers // Custom headers
//#include "callbacks.h" //#include "callbacks.h"
@ -41,9 +47,16 @@
} \ } \
} while (0) \ } while (0) \
// Enums
enum class RenderRez {
FIT,
R800x800,
R720p,
R1080p,
R2k
};
// Custom types // Custom types
struct DeletionQueue { struct DeletionQueue {
std::deque<std::function<void()>> deletors; std::deque<std::function<void()>> deletors;
@ -74,6 +87,42 @@ struct AllocatedImage {
VkFormat imageFormat; VkFormat imageFormat;
}; };
struct AllocatedBuffer {
VkBuffer buffer;
VmaAllocation allocation;
VmaAllocationInfo info;
uint32_t size; // In bytes
};
struct Vertex {
alignas(16) glm::vec3 position;
float uv_x;
alignas(16) glm::vec3 normal;
float uv_y;
glm::vec4 color;
};
// Holds the ressouces required for a mesh
struct GPUMeshBuffers {
AllocatedBuffer indexBuffer;
AllocatedBuffer vertexBuffer;
VkDeviceAddress vertexBufferAddress;
};
struct GPUDrawPushConstants {
glm::mat4 worldMatrix;
VkDeviceAddress vertexBuffer;
};
// Engine config
struct EngineConfig {
int gpuIndex {-1};
std::string modelPath;
};
// "Global" ? (I hope so) logger
Logger logger;
#endif #endif

View File

@ -17,7 +17,7 @@ class Callback {
void Callback::keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods) { void Callback::keyboardCallback(GLFWwindow* window, int key, int scancode, int action, int mods) {
#ifdef DEBUG #ifdef DEBUG
fmt::println("[Engine:Info] Key pressed, key {}", key); logger.logRAM(LogModule::GLFW, LogLevel::EINFO, "Key pressed, key {}", key);
#endif #endif
} }

File diff suppressed because it is too large Load Diff

View File

@ -2,6 +2,7 @@
#define INITIALIZERS_H #define INITIALIZERS_H
// Normal header // Normal header
#include "Common/Types.h" #include "Common/Types.h"
#include "simdjson.h"
#include <vulkan/vulkan_core.h> #include <vulkan/vulkan_core.h>
namespace vkinit { namespace vkinit {
@ -64,12 +65,19 @@ namespace vkinit {
VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/ VkImageLayout layout /*= VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL*/
); );
VkRenderingAttachmentInfo depthAttachmentInfo(
VkImageView view,
VkImageLayout layout
);
VkRenderingInfo renderingInfo( VkRenderingInfo renderingInfo(
VkExtent2D renderExtent, VkExtent2D renderExtent,
VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* colorAttachment,
VkRenderingAttachmentInfo* depthAttachment VkRenderingAttachmentInfo* depthAttachment
); );
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo();
VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo( VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo(
VkShaderStageFlagBits stage, VkShaderStageFlagBits stage,
VkShaderModule shaderModule, VkShaderModule shaderModule,
@ -287,6 +295,27 @@ namespace vkinit {
return colorAttachment; return colorAttachment;
} }
VkRenderingAttachmentInfo depthAttachmentInfo(
VkImageView view,
VkImageLayout layout
) {
VkRenderingAttachmentInfo depthAttachment {
.sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO,
.pNext = nullptr,
.imageView = view,
.imageLayout = layout,
.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
.storeOp = VK_ATTACHMENT_STORE_OP_STORE,
.clearValue = {
.depthStencil = {
.depth = 0.0f
}
}
};
return depthAttachment;
}
VkRenderingInfo renderingInfo( VkRenderingInfo renderingInfo(
VkExtent2D renderExtent, VkExtent2D renderExtent,
VkRenderingAttachmentInfo* colorAttachment, VkRenderingAttachmentInfo* colorAttachment,
@ -310,6 +339,21 @@ namespace vkinit {
return renderInfo; return renderInfo;
} }
VkPipelineLayoutCreateInfo pipelineLayoutCreateInfo() {
VkPipelineLayoutCreateInfo info {
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
.pNext = nullptr,
// Empty defaults
.flags = 0,
.setLayoutCount = 0,
.pSetLayouts = nullptr,
.pushConstantRangeCount = 0,
.pPushConstantRanges = nullptr,
};
return info;
}
VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo( VkPipelineShaderStageCreateInfo pipelineShaderStageCreateInfo(
VkShaderStageFlagBits stage, VkShaderStageFlagBits stage,
VkShaderModule shaderModule, VkShaderModule shaderModule,

197
src/Engine/engine/loader.h Normal file
View File

@ -0,0 +1,197 @@
#ifndef LOADER_H
#define LOADER_H
// Header
// Custom includes
#include "Common/Types.h"
// Other includes
#include <cstdint>
#include <unordered_map>
#include <filesystem>
// Stucts
struct GeoSurface {
uint32_t startIndex;
uint32_t count;
};
struct MeshAsset {
std::string name;
std::vector<GeoSurface> surfaces;
GPUMeshBuffers meshBuffers;
};
// Forward declaration
class Engine;
#endif
#ifdef LOADER_IMPL
#ifndef LOADER_IMPL_H
#define LOADER_IMPL_H
// Main code file
// Includes
#include <fastgltf/core.hpp>
#include <fastgltf/types.hpp>
#include <fastgltf/glm_element_traits.hpp>
#include <fastgltf/tools.hpp>
constexpr bool OverrideColors = true;
std::optional<std::vector<std::shared_ptr<MeshAsset>>> loadGltfMeshes(
Engine* engine,
std::filesystem::path filePath
) {
// Todo:
// Use util functions for attributes
auto& logger = engine->_logger; // Uses the main logger
logger.logAll(LogModule::ENGINE, LogLevel::EINFO, "Loading GLTF: {}", filePath.string());
fastgltf::Parser parser;
fastgltf::Asset gltf;
auto data = fastgltf::GltfDataBuffer::FromPath(filePath);
constexpr auto gltfOptions {
fastgltf::Options::LoadExternalBuffers
};
auto load = parser.loadGltf(
data.get(),
filePath.parent_path(),
gltfOptions
);
if(load) {
gltf = std::move(load.get());
} else {
logger.logFatal(LogModule::ENGINE, "Failed to load gltf: {}", fastgltf::to_underlying(load.error()));
}
std::vector<std::shared_ptr<MeshAsset>> meshes;
// Use the same vectors for all meshes
// so that the memory doesn't reallocate
// as often
std::vector<uint32_t> indices;
std::vector<Vertex> vertices;
// Now, some gltf gymnastics to get data into the correct buffers.
/*
====================================
The following comments are notes,
to help me build the loader,
based on the new fastgltf api
(the vkguide is using an older api)
====================================
By reading the vkguide, I can see that
he's iterating on "gltf" which is an Asset.
In the official docs, it is stated we can get direct
references to the Asset class, using pointers (->)
For exemple with buffers: asset->buffers
*/
for(fastgltf::Mesh& mesh : gltf.meshes) { // Perhaps error ?
MeshAsset newmesh;
newmesh.name = mesh.name;
// Clear the arrays for memory optimizations
indices.clear();
vertices.clear();
for(auto&& p : mesh.primitives) { // 100% Error, use pointers ig ?
GeoSurface newSurface;
newSurface.startIndex = (uint32_t)indices.size();
newSurface.count = (uint32_t)gltf.accessors[p.indicesAccessor.value()].count;
size_t initialVTX = vertices.size();
// -- Indices --
{
fastgltf::Accessor& indexAccessor = gltf.accessors[p.indicesAccessor.value()];
indices.reserve(indices.size() + indexAccessor.count); // Memory alloc ig ?
fastgltf::iterateAccessor<std::uint32_t>(gltf, indexAccessor,
[&](std::uint32_t idx) {
indices.push_back(idx + initialVTX);
}
);
}
// -- Vertex Positions --
{
auto posIt = p.findAttribute("POSITION");
if (posIt == p.attributes.end()) {
logger.logFatal(LogModule::ENGINE, "Primitive without POSITION attribute");
return std::nullopt;
}
fastgltf::Accessor& posAccessor = gltf.accessors[posIt->accessorIndex];
vertices.resize(vertices.size() + posAccessor.count);
fastgltf::iterateAccessorWithIndex<glm::vec3>(gltf, posAccessor,
[&](glm::vec3 v, size_t index) {
Vertex newvtx;
newvtx.position = v;
newvtx.normal = { 1.0f, 0.0f, 0.0f };
newvtx.color = glm::vec4(1.0f);
newvtx.uv_x = 0.0f;
newvtx.uv_y = 0.0f;
vertices[initialVTX + index] = newvtx;
}
);
}
// --- Normals ---
if (auto normals = p.findAttribute("NORMAL"); normals != p.attributes.end()) {
fastgltf::iterateAccessorWithIndex<glm::vec3>(gltf, gltf.accessors[normals->accessorIndex],
[&](glm::vec3 v, size_t index) {
vertices[initialVTX + index].normal = v;
}
);
}
// --- UVs ---
if (auto uv = p.findAttribute("TEXCOORD_0"); uv != p.attributes.end()) {
fastgltf::iterateAccessorWithIndex<glm::vec2>(gltf, gltf.accessors[uv->accessorIndex],
[&](glm::vec2 v, size_t index) {
vertices[initialVTX + index].uv_x = v.x;
vertices[initialVTX + index].uv_y = v.y;
}
);
}
// --- Vertex Colors ---
if (auto colors = p.findAttribute("COLOR_0"); colors != p.attributes.end()) {
fastgltf::iterateAccessorWithIndex<glm::vec4>(gltf, gltf.accessors[colors->accessorIndex],
[&](glm::vec4 v, size_t index) {
vertices[initialVTX + index].color = v;
}
);
}
newmesh.surfaces.push_back(newSurface);
}
// Display vertex normals
if (OverrideColors) {
for (Vertex& vtx : vertices) {
vtx.color = glm::vec4(vtx.normal, 1.0f);
}
}
newmesh.meshBuffers = engine->uploadMesh(indices, vertices);
meshes.emplace_back(std::make_shared<MeshAsset>(std::move(newmesh)));
}
// Debug things
#ifdef DEBUG
if(fastgltf::validate(load.get()) != fastgltf::Error::None) {
logger.logFatal(LogModule::ENGINE, "gltf file is not up to spec !");
}
#endif
return meshes;
}
#endif
#endif

View File

@ -1,3 +1,8 @@
/*
Todo:
Create a temporary struct, to have the correct structure
then copy it to the class member
*/
#ifndef PIPELINES_H #ifndef PIPELINES_H
#define PIPELINES_H #define PIPELINES_H
// Normal header // Normal header
@ -28,6 +33,7 @@ class PipelineBuilder {
VkPipelineLayout _pipelineLayout; VkPipelineLayout _pipelineLayout;
VkPipelineDepthStencilStateCreateInfo _depthStencil; VkPipelineDepthStencilStateCreateInfo _depthStencil;
VkPipelineRenderingCreateInfo _renderInfo; VkPipelineRenderingCreateInfo _renderInfo;
VkFormat _colorAttachmentFormat;
PipelineBuilder() { clear(); } PipelineBuilder() { clear(); }
@ -57,6 +63,8 @@ class PipelineBuilder {
void setMultisamplingNone(); void setMultisamplingNone();
void enableBlendingAdditive();
void enableBlendingAlphaBlend();
void disableBlending(); void disableBlending();
void setColorAttachmentFormat( void setColorAttachmentFormat(
@ -68,6 +76,10 @@ class PipelineBuilder {
); );
void disableDepthtest(); void disableDepthtest();
void enableDepthtest(
bool depthWriteEnable,
VkCompareOp op
);
}; };
#endif #endif
@ -323,6 +335,28 @@ void PipelineBuilder::setMultisamplingNone() {
_multisampling.alphaToOneEnable = VK_FALSE; _multisampling.alphaToOneEnable = VK_FALSE;
} }
void PipelineBuilder::enableBlendingAdditive() {
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
_colorBlendAttachment.blendEnable = VK_TRUE;
_colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
_colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
_colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
_colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
void PipelineBuilder::enableBlendingAlphaBlend() {
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
_colorBlendAttachment.blendEnable = VK_TRUE;
_colorBlendAttachment.srcColorBlendFactor = VK_BLEND_FACTOR_SRC_ALPHA;
_colorBlendAttachment.dstColorBlendFactor = VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA;
_colorBlendAttachment.colorBlendOp = VK_BLEND_OP_ADD;
_colorBlendAttachment.srcAlphaBlendFactor = VK_BLEND_FACTOR_ONE;
_colorBlendAttachment.dstAlphaBlendFactor = VK_BLEND_FACTOR_ZERO;
_colorBlendAttachment.alphaBlendOp = VK_BLEND_OP_ADD;
}
void PipelineBuilder::disableBlending() { void PipelineBuilder::disableBlending() {
// Default write mask // Default write mask
_colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; _colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
@ -330,6 +364,15 @@ void PipelineBuilder::disableBlending() {
_colorBlendAttachment.blendEnable = VK_FALSE; _colorBlendAttachment.blendEnable = VK_FALSE;
} }
void PipelineBuilder::setColorAttachmentFormat(
VkFormat format
) {
_colorAttachmentFormat = format;
// connect the format to the renderInfo structure
_renderInfo.colorAttachmentCount = 1;
_renderInfo.pColorAttachmentFormats = &_colorAttachmentFormat;
}
void PipelineBuilder::setDepthFormat( void PipelineBuilder::setDepthFormat(
VkFormat format VkFormat format
) { ) {
@ -348,5 +391,20 @@ void PipelineBuilder::disableDepthtest() {
_depthStencil.maxDepthBounds = 1.0f; _depthStencil.maxDepthBounds = 1.0f;
} }
void PipelineBuilder::enableDepthtest(
bool depthWriteEnable,
VkCompareOp op
) {
_depthStencil.depthTestEnable = VK_TRUE;
_depthStencil.depthWriteEnable = depthWriteEnable;
_depthStencil.depthCompareOp = op;
_depthStencil.depthBoundsTestEnable = VK_FALSE;
_depthStencil.stencilTestEnable = VK_FALSE;
_depthStencil.front = {};
_depthStencil.back = {};
_depthStencil.minDepthBounds = 0.0f;
_depthStencil.maxDepthBounds = 1.0f;
}
#endif #endif
#endif #endif

View File

@ -1,18 +1,99 @@
/*
Copyright Alexandre Delcamp-Enache, 2026
Based on vkguide.dev
See engine.h for extensive documentation
Also, checkout the roadmap
*/
#define ENGINE_IMPL #define ENGINE_IMPL
#include "engine/engine.h" #include "engine/engine.h"
#include "CLI/CLI.hpp"
class ArgHandler {
public:
CLI::App* _run;
// All options
bool _listGPU {false};
EngineConfig config;
void buildArgs() {
// Setup
// Subcommands
_run = _app.add_subcommand("run");
// Main options/flags
_app.add_flag("--list-gpu, -l", _listGPU, "Lists available Graphics cards, useful for debugging");
_app.set_version_flag("--version, -v", BUILD_ID);
// Help
//_app.set_help_all_flag("--help-all", "Expand all help");
_app.set_help_flag();
_app.set_help_all_flag("--help, -h", "Print help for all subcommands");
// Subcommand options/flags
// Run
_run->add_option("--gpu, -g", config.gpuIndex, "Manually select a GPU");
_run->add_option("--model, -m", config.modelPath, "Overwrites the default model");
}
int dispatch(int argc, char* argv[]) {
CLI11_PARSE(_app, argc, argv);
return 0;
}
void printHelp() {
fmt::println("{}", _app.help());
}
private:
CLI::App _app;
};
int main(int argc, char* argv[]) { int main(int argc, char* argv[]) {
// Classes we need
Engine engine; Engine engine;
ArgHandler handler;
// Exemple of overwriting a class value // Exemple of overwriting a class value
//engine._windowExtent = { 67, 67 }; //engine._windowExtent = { 67, 67 };
handler.buildArgs();
if (argc == 1) {
handler.printHelp();
fmt::println("Please use -h or --help to see all available options.");
return 0;
}
// Checks for -h flag
int result = handler.dispatch(argc, argv);
if(result != 0) return result;
if (handler._run->parsed() &&
handler._run->get_help_ptr()->as<bool>()) {
return 0;
}
if(handler._listGPU) {
engine.getAvailableGPU();
return 0;
}
if(handler._run->parsed()){
engine.parseConfig(
handler.config
);
engine.init(); engine.init();
engine.run(); engine.run();
engine.cleanup(); engine.cleanup();
}
return 0; return 0;
} }

@ -1 +0,0 @@
Subproject commit 5220a3f48d39c000da8b46fb0fccf3dd62695c51