Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
101 commits
Select commit Hold shift + click to select a range
12f357f
First commit of the new "simple engine" tutorial. This is a VERY ear…
gpx1000 Jul 14, 2025
7e419d5
Refactor GPU optimization sections to generalize vendor-specific reco…
gpx1000 Jul 14, 2025
4644950
Refactor mobile GPU optimization sections and enhance Vulkan extensio…
gpx1000 Jul 14, 2025
2edbd75
Add detailed section on rendergraphs and synchronization in Vulkan
gpx1000 Jul 14, 2025
b476bd1
Add architectural pattern diagrams and refine related sections
gpx1000 Jul 18, 2025
f1d10cf
Add explanatory note on windowing libraries in input handling tutorial
gpx1000 Jul 18, 2025
2a350b2
closer to getting engine working.
gpx1000 Jul 20, 2025
2d46280
address feedback
gpx1000 Jul 22, 2025
3b3dc05
address feedback
gpx1000 Jul 22, 2025
6cf03fc
address feedback
gpx1000 Jul 22, 2025
50d78a7
add the flowchart to the rendering pipeline.
gpx1000 Jul 22, 2025
9b2c781
describe Rendergraphs and Dynamic Rendering
gpx1000 Jul 22, 2025
ddd1177
address comments.
gpx1000 Jul 22, 2025
5ec2035
add the requested appendix.adoc
gpx1000 Jul 22, 2025
31ded49
add the requested appendix.adoc
gpx1000 Jul 23, 2025
659ecb1
address the requested items
gpx1000 Jul 23, 2025
bd98b2d
address the requested items
gpx1000 Jul 23, 2025
8b83ead
address the requested items
gpx1000 Jul 23, 2025
9b2343a
address the requested items
gpx1000 Jul 23, 2025
7734f21
Engine now builds and runs. IMGUI having issues.
gpx1000 Jul 23, 2025
b8a9b39
Engine now renders. Bunch of validation errors and it looks like img…
gpx1000 Jul 23, 2025
e773353
address comments.
gpx1000 Jul 24, 2025
6256f77
address comments.
gpx1000 Jul 24, 2025
e6b8583
It runs now, IMGUI is happier.
gpx1000 Jul 24, 2025
e3f6fc6
everything runs and can close without validation warnings other than …
gpx1000 Jul 24, 2025
4a3b450
everything runs and can close without validation warnings other than …
gpx1000 Jul 24, 2025
0833166
audio HRTF works well and debug switch to turn on CPU only mode vs GP…
gpx1000 Jul 24, 2025
9513597
audio fully works, GPU HRTF works as well as CPU HRTF.
gpx1000 Jul 25, 2025
86c396a
The bistro scene now loads. Still have some issues with PBR but I th…
gpx1000 Jul 25, 2025
a62e4a9
make the hrtf listener sync with the camera location and rotation.
gpx1000 Jul 25, 2025
14fc6b1
Lighting working for non PBR code, and PBR code seems to be relativel…
gpx1000 Jul 25, 2025
b998a13
fix for formating the list.
gpx1000 Jul 29, 2025
8be59f4
PBR is working. KTX2 with BasisU is working.
gpx1000 Jul 29, 2025
be45542
Update 04_rendering_approaches.adoc
gpx1000 Jul 29, 2025
8bdf3d1
Update 04_rendering_approaches.adoc
gpx1000 Jul 30, 2025
e80fd23
address comments
gpx1000 Jul 30, 2025
20a9ade
Merge remote-tracking branch 'origin/Simple-Game-Engine' into Simple-…
gpx1000 Jul 30, 2025
d834c39
address comments
gpx1000 Jul 31, 2025
ea39e65
address comments
gpx1000 Jul 31, 2025
858b792
address comments
gpx1000 Jul 31, 2025
815aa79
Need to investigate a few things, (physics isn't colliding against th…
gpx1000 Jul 31, 2025
bdc1845
add in the dependences install scripts.
gpx1000 Jul 31, 2025
04c8b38
Merge branch 'refs/heads/upstream-main' into Simple-Game-Engine
gpx1000 Jul 31, 2025
cdb01db
attempt to fancy fix the windows install script.
gpx1000 Aug 1, 2025
16019ca
CMake: use PLATFORM_* defines via ANDROID, fix glfw condition, make s…
gpx1000 Aug 8, 2025
4b8198d
Fix the pathing for install_dependencies_windows.bat also fix CMakeLi…
gpx1000 Aug 8, 2025
14dcb35
Add instancing support, remove unused STB dependency, and fetch Bistr…
gpx1000 Aug 10, 2025
dd9713a
Refactor Vulkan memory handling, physics GPU initialization, and coll…
gpx1000 Aug 10, 2025
27715c0
address several comments (more still need to be addressed). And fix …
gpx1000 Aug 10, 2025
067ea74
Move Renderdoc out of the debug_system.h and into a "real world" rend…
gpx1000 Aug 11, 2025
a5edf28
the lighting in the PBR scene *looks* better. There's still a bit th…
gpx1000 Aug 11, 2025
adf461e
Remove shadows for now. We'll concentrate on them in the samples ver…
gpx1000 Aug 12, 2025
e57bc3d
Fix the string lights.
gpx1000 Aug 13, 2025
e1d7059
committing requested changes in stages.
gpx1000 Aug 15, 2025
1f17074
committing requested changes in stages.
gpx1000 Aug 15, 2025
acfbd6e
committing requested changes in stages.
gpx1000 Aug 15, 2025
5e38540
committing requested changes in stages.
gpx1000 Aug 15, 2025
a58b884
committing requested changes in stages.
gpx1000 Aug 15, 2025
4b4a243
committing requested changes in stages.
gpx1000 Aug 15, 2025
6ec7321
committing requested changes in stages.
gpx1000 Aug 15, 2025
8ecae4e
committing requested changes in stages.
gpx1000 Aug 15, 2025
345b137
committing requested changes in stages.
gpx1000 Aug 15, 2025
11e9a65
committing requested changes in stages.
gpx1000 Aug 15, 2025
5e6209c
committing requested changes in stages.
gpx1000 Aug 15, 2025
25e66d5
committing requested changes in stages.
gpx1000 Aug 15, 2025
5849fa5
switch from link to xref.
gpx1000 Aug 15, 2025
f1df3d2
addressing more comments.
gpx1000 Aug 15, 2025
7eaa47e
addressing more comments.
gpx1000 Aug 15, 2025
92c7f7d
addressing more comments.
gpx1000 Aug 15, 2025
625eb71
addressing more comments.
gpx1000 Aug 15, 2025
60ee95d
addressing more comments.
gpx1000 Aug 15, 2025
23952bc
addressing more comments.
gpx1000 Aug 15, 2025
65e5db3
addressing more comments.
gpx1000 Aug 15, 2025
e564b29
addressing more comments.
gpx1000 Aug 15, 2025
7b3e016
addressing more comments.
gpx1000 Aug 15, 2025
7bf9dab
addressing more comments.
gpx1000 Aug 15, 2025
47a6baa
addressing more comments.
gpx1000 Aug 15, 2025
44e7f38
addressing more comments.
gpx1000 Aug 15, 2025
dd51a38
addressing more comments.
gpx1000 Aug 15, 2025
f713e9c
addressing more comments.
gpx1000 Aug 15, 2025
9705b60
addressing more comments.
gpx1000 Aug 15, 2025
921eed4
addressing more comments.
gpx1000 Aug 15, 2025
2a22079
addressing more comments.
gpx1000 Aug 15, 2025
41e336e
addressing more comments.
gpx1000 Aug 15, 2025
b78f8b2
addressing more comments.
gpx1000 Aug 16, 2025
5c7a132
addressing more comments.
gpx1000 Aug 16, 2025
560b9f3
addressing more comments.
gpx1000 Aug 16, 2025
6db6b9d
addressing more comments.
gpx1000 Aug 16, 2025
02baf4d
addressing more comments.
gpx1000 Aug 16, 2025
0b0dddb
addressing more comments.
gpx1000 Aug 16, 2025
ccb5c15
addressing more comments.
gpx1000 Aug 19, 2025
aa321c0
addressing more comments.
gpx1000 Aug 19, 2025
5c4ec27
addressing more comments.
gpx1000 Aug 19, 2025
b4d6226
addressing more comments.
gpx1000 Aug 19, 2025
a8d11c6
addressing more comments.
gpx1000 Aug 19, 2025
b167c70
addressing more comments.
gpx1000 Aug 19, 2025
276d1cb
addressing more comments.
gpx1000 Aug 21, 2025
6e8adb4
implementing Spec-Gloss workflow and transmission materials.
gpx1000 Aug 25, 2025
e1ac508
updating nlohmann_json to v3.12.0.
gpx1000 Aug 25, 2025
bbbae41
update the default screenshot.
gpx1000 Aug 25, 2025
03d05cf
implementing support for asynchronous texture loading and improved Vu…
gpx1000 Aug 26, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
314 changes: 201 additions & 113 deletions attachments/simple_engine/audio_system.cpp

Large diffs are not rendered by default.

14 changes: 10 additions & 4 deletions attachments/simple_engine/audio_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,11 @@ class AudioSystem {
*/
AudioSystem() = default;

/**
* @brief Flush audio output: clears pending processing and device buffers so playback restarts cleanly.
*/
void FlushOutput();

/**
* @brief Destructor for proper cleanup.
*/
Expand All @@ -165,7 +170,7 @@ class AudioSystem {
* @brief Update the audio system.
* @param deltaTime The time elapsed since the last update.
*/
void Update(float deltaTime);
void Update(std::chrono::milliseconds deltaTime);

/**
* @brief Load an audio file.
Expand Down Expand Up @@ -318,8 +323,9 @@ class AudioSystem {
std::vector<float> inputBuffer;
std::vector<float> outputBuffer;
float sourcePosition[3];
uint32_t sampleCount;
uint32_t actualSamplesProcessed;
uint32_t sampleCount; // total frames in input/output (may include history)
uint32_t actualSamplesProcessed; // frames to write this tick (new part)
uint32_t trimFront; // frames to skip from output front (history length)
AudioOutputDevice* outputDevice;
float masterVolume;
};
Expand Down Expand Up @@ -392,5 +398,5 @@ class AudioSystem {
* @param actualSamplesProcessed The number of samples actually processed.
* @return True if the task was submitted successfully, false otherwise.
*/
bool submitAudioTask(const float* inputBuffer, uint32_t sampleCount, const float* sourcePosition, uint32_t actualSamplesProcessed);
bool submitAudioTask(const float* inputBuffer, uint32_t sampleCount, const float* sourcePosition, uint32_t actualSamplesProcessed, uint32_t trimFront);
};
1 change: 0 additions & 1 deletion attachments/simple_engine/component.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
#include "component.h"
#include "entity.h"

// Most of the Component class implementation is in the header file
// This file is mainly for any methods that need to access the Entity class
Expand Down
4 changes: 2 additions & 2 deletions attachments/simple_engine/component.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#pragma once

#include <memory>
#include <chrono>
#include <string>

// Forward declaration
Expand Down Expand Up @@ -44,7 +44,7 @@ class Component {
* Called every frame.
* @param deltaTime The time elapsed since the last frame.
*/
virtual void Update(float deltaTime) {}
virtual void Update(std::chrono::milliseconds deltaTime) {}

/**
* @brief Render the component.
Expand Down
33 changes: 17 additions & 16 deletions attachments/simple_engine/engine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <chrono>
#include <algorithm>
#include <ranges>
#include <stdexcept>
#include <iostream>
#include <random>
Expand Down Expand Up @@ -122,11 +123,11 @@ void Engine::Run() {
}

// Calculate delta time
deltaTime = CalculateDeltaTime();
deltaTimeMs = CalculateDeltaTimeMs();

// Update frame counter and FPS
frameCount++;
fpsUpdateTimer += deltaTime;
fpsUpdateTimer += deltaTimeMs.count() * 0.001f;

// Update window title with FPS and frame time every second
if (fpsUpdateTimer >= 1.0f) {
Expand All @@ -147,7 +148,7 @@ void Engine::Run() {
}

// Update
Update(deltaTime);
Update(deltaTimeMs);

// Render
Render();
Expand Down Expand Up @@ -369,7 +370,7 @@ void Engine::handleKeyInput(uint32_t key, bool pressed) {
}
}

void Engine::Update(float deltaTime) {
void Engine::Update(TimeDelta deltaTime) {
// Debug: Verify Update method is being called
static int updateCallCount = 0;
updateCallCount++;
Expand Down Expand Up @@ -415,27 +416,27 @@ void Engine::Render() {
renderer->Render(entities, activeCamera, imguiSystem.get());
}

float Engine::CalculateDeltaTime() {
std::chrono::milliseconds Engine::CalculateDeltaTimeMs() {
// Get current time using a steady clock to avoid system time jumps
uint64_t currentTime = static_cast<uint64_t>(
std::chrono::duration_cast<std::chrono::milliseconds>(
std::chrono::steady_clock::now().time_since_epoch()
).count()
);

// Initialize lastFrameTime on first call
if (lastFrameTime == 0) {
lastFrameTime = currentTime;
return 0.016f; // ~16ms as a sane initial guess
// Initialize lastFrameTimeMs on first call
if (lastFrameTimeMs == 0) {
lastFrameTimeMs = currentTime;
return std::chrono::milliseconds(16); // ~16ms as a sane initial guess
}

// Calculate delta time in milliseconds
uint64_t delta = currentTime - lastFrameTime;
uint64_t delta = currentTime - lastFrameTimeMs;

// Update last frame time
lastFrameTime = currentTime;
lastFrameTimeMs = currentTime;

return static_cast<float>(delta) / 1000.0f;
return std::chrono::milliseconds(static_cast<long long>(delta));
}

void Engine::HandleResize(int width, int height) const {
Expand All @@ -458,7 +459,7 @@ void Engine::HandleResize(int width, int height) const {
}
}

void Engine::UpdateCameraControls(float deltaTime) const {
void Engine::UpdateCameraControls(TimeDelta deltaTime) const {
if (!activeCamera) return;

// Get a camera transform component
Expand Down Expand Up @@ -492,7 +493,7 @@ void Engine::UpdateCameraControls(float deltaTime) const {

// Manual camera controls (only when tracking is disabled)
// Calculate movement speed
float velocity = cameraControl.cameraSpeed * deltaTime;
float velocity = cameraControl.cameraSpeed * deltaTime.count() * .001f;

// Calculate camera direction vectors based on yaw and pitch
glm::vec3 front;
Expand Down Expand Up @@ -859,10 +860,10 @@ void Engine::RunAndroid() {
// We just need to update and render when the platform is ready

// Calculate delta time
deltaTime = CalculateDeltaTime();
deltaTimeMs = CalculateDeltaTimeMs();

// Update
Update(deltaTime);
Update(deltaTimeMs);

// Render
Render();
Expand Down
24 changes: 16 additions & 8 deletions attachments/simple_engine/engine.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <vector>
#include <memory>
#include <unordered_map>
#include <chrono>

#include "platform.h"
#include "renderer.h"
Expand All @@ -23,6 +24,7 @@
*/
class Engine {
public:
using TimeDelta = std::chrono::milliseconds;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Throughout the code, you're sometimes using TimeDelta, and sometimes using std::chrono::milliseconds. Maybe you should use just one of them?

/**
* @brief Default constructor.
*/
Expand Down Expand Up @@ -167,7 +169,11 @@ class Engine {
* @param enableValidationLayers Whether to enable Vulkan validation layers.
* @return True if initialization was successful, false otherwise.
*/
#if defined(NDEBUG)
bool InitializeAndroid(android_app* app, const std::string& appName, bool enableValidationLayers = false);
#else
bool InitializeAndroid(android_app* app, const std::string& appName, bool enableValidationLayers = true);
#endif

/**
* @brief Run the engine on Android.
Expand Down Expand Up @@ -197,8 +203,9 @@ class Engine {
bool running = false;

// Delta time calculation
float deltaTime = 0.0f;
uint64_t lastFrameTime = 0;
// deltaTimeMs: time since last frame in milliseconds (for clarity)
std::chrono::milliseconds deltaTimeMs{0};
uint64_t lastFrameTimeMs = 0;

// Frame counter and FPS calculation
uint64_t frameCount = 0;
Expand Down Expand Up @@ -254,7 +261,7 @@ class Engine {

PhysicsScaling physicsScaling;

// Pending ball creation data (to avoid memory pool constraints during rendering)
// Pending ball creation data
struct PendingBall {
glm::vec3 spawnPosition;
glm::vec3 throwDirection;
Expand All @@ -269,18 +276,19 @@ class Engine {
* @brief Update the engine state.
* @param deltaTime The time elapsed since the last update.
*/
void Update(float deltaTime);
// Accepts a time delta in milliseconds for clarity
void Update(TimeDelta deltaTime);

/**
* @brief Render the scene.
*/
void Render();

/**
* @brief Calculate the delta time between frames.
* @return The delta time in seconds.
* @brief Calculate the time delta between frames.
* @return The delta time in milliseconds (steady_clock based).
*/
float CalculateDeltaTime();
std::chrono::milliseconds CalculateDeltaTimeMs();

/**
* @brief Handle window resize events.
Expand All @@ -293,7 +301,7 @@ class Engine {
* @brief Update camera controls based on input state.
* @param deltaTime The time elapsed since the last update.
*/
void UpdateCameraControls(float deltaTime) const;
void UpdateCameraControls(TimeDelta deltaTime) const;

/**
* @brief Generate random PBR material properties for the ball.
Expand Down
2 changes: 1 addition & 1 deletion attachments/simple_engine/entity.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ void Entity::Initialize() {
}
}

void Entity::Update(float deltaTime) {
void Entity::Update(std::chrono::milliseconds deltaTime) {
if (!active) return;

for (auto& component : components) {
Expand Down
40 changes: 12 additions & 28 deletions attachments/simple_engine/entity.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@
#include <memory>
#include <string>
#include <algorithm>
#include <typeindex>
#include <unordered_map>
#include <chrono>
#include <type_traits>

#include "component.h"
Expand All @@ -21,7 +20,6 @@ class Entity {
std::string name;
bool active = true;
std::vector<std::unique_ptr<Component>> components;
std::unordered_map<std::type_index, Component*> componentMap;

public:
/**
Expand Down Expand Up @@ -62,7 +60,7 @@ class Entity {
* @brief Update all components of the entity.
* @param deltaTime The time elapsed since the last frame.
*/
void Update(float deltaTime);
void Update(std::chrono::milliseconds deltaTime);

/**
* @brief Render all components of the entity.
Expand All @@ -87,10 +85,7 @@ class Entity {
// Set the owner
componentPtr->SetOwner(this);

// Add to the map for quick lookup
componentMap[std::type_index(typeid(T))] = componentPtr;

// Add to the vector for ownership
// Add to the vector for ownership and iteration
components.push_back(std::move(component));

// Initialize the component
Expand All @@ -108,11 +103,12 @@ class Entity {
T* GetComponent() const {
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");

auto it = componentMap.find(std::type_index(typeid(T)));
if (it != componentMap.end()) {
return static_cast<T*>(it->second);
// Search from the back to preserve previous behavior of returning the last-added component of type T
for (auto it = components.rbegin(); it != components.rend(); ++it) {
if (auto* casted = dynamic_cast<T*>(it->get())) {
return casted;
}
}

return nullptr;
}

Expand All @@ -125,21 +121,9 @@ class Entity {
bool RemoveComponent() {
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");

auto it = componentMap.find(std::type_index(typeid(T)));
if (it != componentMap.end()) {
Component* componentPtr = it->second;

// Remove from the map
componentMap.erase(it);

// Find and remove from the vector
auto vecIt = std::find_if(components.begin(), components.end(),
[componentPtr](const std::unique_ptr<Component>& comp) {
return comp.get() == componentPtr;
});

if (vecIt != components.end()) {
components.erase(vecIt);
for (auto it = components.rbegin(); it != components.rend(); ++it) {
if (dynamic_cast<T*>(it->get()) != nullptr) {
components.erase(std::next(it).base());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you erase std::next(it), not it?

return true;
}
}
Expand All @@ -155,6 +139,6 @@ class Entity {
template<typename T>
bool HasComponent() const {
static_assert(std::is_base_of<Component, T>::value, "T must derive from Component");
return componentMap.contains(std::type_index(typeid(T)));
return GetComponent<T>() != nullptr;
}
};
29 changes: 3 additions & 26 deletions attachments/simple_engine/imgui_system.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -281,6 +281,7 @@ void ImGuiSystem::NewFrame() {
if (ImGui::Button("Play")) {
if (currentSource) {
currentSource->Play();
if (audioSystem) { audioSystem->FlushOutput(); }
if (useDebugPing) {
std::cout << "Started playing debug ping (800Hz sine wave) with HRTF processing" << std::endl;
} else {
Expand Down Expand Up @@ -311,34 +312,10 @@ void ImGuiSystem::NewFrame() {
ImGui::Text("Use directional buttons to move the audio source in 3D space");
ImGui::Text("You should hear the audio move around you!");

// HRTF Processing Mode Selection
// HRTF Processing Mode: GPU only (checkbox removed)
ImGui::Separator();
ImGui::Text("HRTF Processing Mode:");

static bool cpuOnlyMode = false;
static bool initialized = false;

// Initialize checkbox state to match audio system state
if (!initialized && audioSystem) {
cpuOnlyMode = audioSystem->IsHRTFCPUOnly();
initialized = true;
}

if (ImGui::Checkbox("Force CPU-only HRTF processing", &cpuOnlyMode)) {
if (audioSystem) {
audioSystem->SetHRTFCPUOnly(cpuOnlyMode);
std::cout << "HRTF processing mode changed to: " << (cpuOnlyMode ? "CPU-only" : "Vulkan shader (when available)") << std::endl;
}
}

// Display current processing mode
if (audioSystem) {
if (audioSystem->IsHRTFCPUOnly()) {
ImGui::Text("Current Mode: CPU-only processing");
} else {
ImGui::Text("Current Mode: Vulkan shader processing (when available)");
}
}
ImGui::Text("Current Mode: Vulkan shader processing (GPU)");
} else {
ImGui::Text("HRTF Processing: DISABLED");
}
Expand Down
Loading
Loading