Skip to content

feat(engine): fill 3 cross-engine feature gaps (clouds, HRTF, directi…#491

Merged
Krilliac merged 6 commits into
Workingfrom
claude/evaluate-engine-features-94eP0
Apr 18, 2026
Merged

feat(engine): fill 3 cross-engine feature gaps (clouds, HRTF, directi…#491
Krilliac merged 6 commits into
Workingfrom
claude/evaluate-engine-features-94eP0

Conversation

@Krilliac

Copy link
Copy Markdown
Owner

…onal streaming)

  1. VolumetricCloudSystem (Graphics/VolumetricClouds.{h,cpp}) — Decima- style ray-marched clouds with two-scale Perlin+Worley noise, 2D weather map, height gradient per cloud type, two-lobe Henyey- Greenstein phase, light-march self-shadowing. CPU reference + GPU feeder (R8 3D + RG8 2D). Wired into GameplayLifecycleShared.

  2. HRTFProcessor (Audio/HRTFProcessor.{h,cpp}) — portable analytical binaural renderer: Woodworth ITD, cos^2 ILD + distance falloff, one-pole head-shadow low-pass on far ear, per-block gain cross-fade. No external HRIR dataset required; measured HRIRs can drop in later.

  3. Directional predictive streaming (SeamlessAreaManager) — added StreamingConfig::directionalBias + directionalDotThreshold, new DirectionalEffectiveDistance() helper reduces radius/sort distance for areas along the velocity / camera vector (RAGE/Decima style).

23 new tests across 3 files. Full suite: 5614/5614 passing.

…onal streaming)

Cross-checked SparkEngine against modern engines (Unreal 5, Unity, Godot,
Bevy, Wicked, Filament, O3DE, The Forge, Decima) to find genuinely
missing features, then implemented the three remaining gaps:

1. VolumetricCloudSystem (Graphics/VolumetricClouds.{h,cpp}) — Decima-
   style ray-marched clouds with two-scale Perlin+Worley noise, 2D
   weather map, height gradient per cloud type, two-lobe Henyey-
   Greenstein phase, light-march self-shadowing. CPU reference +
   GPU feeder (R8 3D + RG8 2D). Wired into GameplayLifecycleShared.

2. HRTFProcessor (Audio/HRTFProcessor.{h,cpp}) — portable analytical
   binaural renderer: Woodworth ITD, cos^2 ILD + distance falloff,
   one-pole head-shadow low-pass on far ear, per-block gain cross-fade.
   No external HRIR dataset required; measured HRIRs can drop in later.

3. Directional predictive streaming (SeamlessAreaManager) — added
   StreamingConfig::directionalBias + directionalDotThreshold, new
   DirectionalEffectiveDistance() helper reduces radius/sort distance
   for areas along the velocity / camera vector (RAGE/Decima style).

23 new tests across 3 files. Full suite: 5614/5614 passing.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: baf5f3fe87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +384 to +385
const float dA = DirectionalEffectiveDistance(areaA.distanceToPlayer, areaA.definition);
const float dB = DirectionalEffectiveDistance(areaB.distanceToPlayer, areaB.definition);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Snapshot player direction before sorting load candidates

The sort comparator now depends on DirectionalEffectiveDistance, which reads live player state each time it is invoked. Because SetPlayerState() is explicitly allowed from other threads, player velocity/direction can change during std::sort, so the comparator may return inconsistent results for the same pair across calls. That violates std::sort’s strict-weak-ordering requirement and can produce undefined behavior or nondeterministic load ordering under normal multithreaded updates.

Useful? React with 👍 / 👎.

Comment on lines +336 to +337
if (std::abs(dirY) < 1e-4f)
return -1.0f;

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Handle horizontal rays that start inside the cloud slab

The slab intersection helper returns -1 whenever dirY is near zero, which makes both intersections invalid and causes an early return with full transmittance. This drops any ray that is parallel to the cloud layer even if its origin is already between baseAltitude and topAltitude, so horizon-level or lateral cloud rays incorrectly render as cloud-free.

Useful? React with 👍 / 👎.

@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage (GCC + lcov)

Utils/Result.h                                 | 100%    29| 0.0%  28|    -    0
Utils/RingBuffer.h                             | 142%    59| 0.0%  84|    -    0
Utils/ScheduledCallback.h                      |    -     0|    -   0|    -    0
Utils/ScopeGuard.h                             | 142%    36| 0.0%  51|    -    0
Utils/ScopedTimer.h                            |25.0%    12| 0.0%   3|    -    0
Utils/Serializer.h                             |86.2%    58| 0.0%  44|    -    0
Utils/ShaderServiceClient.cpp                  |12.2%    41| 0.0%   4|    -    0
Utils/ShaderServiceClient.h                    | 100%     1| 0.0%   1|    -    0
Utils/ShaderServiceProtocol.h                  |11.8%    68| 0.0%   8|    -    0
Utils/SparkConsole.cpp                         |27.2%   151| 0.0%  18|    -    0
Utils/SparkConsole.h                           | 100%     2| 0.0%   2|    -    0
Utils/SparkError.h                             |10.9%    55| 0.0%   6|    -    0
Utils/SplineMath.cpp                           |20.5%    39| 0.0%   5|    -    0
Utils/SplinePath.h                             |    -     0|    -   0|    -    0
Utils/StackTrace.h                             |10.8%    74| 0.0%   8|    -    0
Utils/StateMachine.h                           |85.9%    64| 0.0%  49|    -    0
Utils/StringUtils.h                            |18.1%   116| 0.0%  21|    -    0
Utils/Telemetry.h                              |20.6%   136| 0.0%  23|    -    0
Utils/ThreadDebugger.h                         |11.6%   199| 0.0%  23|    -    0
Utils/ThreadSafeQueue.h                        |27.5%    40| 0.0%  11|    -    0
Utils/Timer.cpp                                |19.4%    36| 0.0%   7|    -    0
Utils/Timer.h                                  | 100%     2| 0.0%   2|    -    0
Utils/TimerManager.h                           |18.6%   102| 0.0%  19|    -    0
Utils/Tween.h                                  |26.3%    38| 0.0%   6|    -    0
Utils/UUID.h                                   |43.2%    37| 0.0%  16|    -    0
Utils/Validate.h                               |    -     0|    -   0|    -    0
Utils/WineDetection.cpp                        |23.1%    39| 0.0%   9|    -    0

[/home/runner/work/SparkEngine/SparkEngine/SparkSDK/Include/Spark/]
IEngineContext.h                               |7300%     1| 0.0%   1|    -    0
ServiceInterfaces.h                            | 200%     3| 0.0%   3|    -    0
Version.h                                      |    -     0|    -   0|    -    0
================================================================================
                                         Total:|30.7% 34598| 0.0%  6k|    -    0

Per-Subsystem Coverage

Subsystem Lines Hit Coverage Threshold Status
AI 3716 942 25.3% 35%
Animation 905 277 30.6% 35%
Audio 0 0 0% 30%
Camera 0 0 0% 40%
Core 4885 2918 59.7% 40%
ECS 426 213 50% 40%
Editor 7411 3046 41.1% 25%
GameModules 6621 3230 48.8% 30%
Graphics 17333 8600 49.6% 30%
Networking 3554 2351 66.2% 35%
Physics 0 0 0% 35%
Scripting 283 80 28.3% 30%
Utils 9778 6050 61.9% 60%

Total: 50.5% (27707/54912 lines)

@github-actions

github-actions Bot commented Apr 17, 2026

Copy link
Copy Markdown
Contributor

❌ CI Error Report

Failed jobs: clang-tidy, linux-clang-Release, macos-Debug, macos-Release
Errors: 2 | Test failures: 0 | Compiler warnings: 6

Build Errors

Other errors (2)
clang++: error: linker command failed with exit code 1 (use -v to see invocation) [linux-clang-Release]
clang++: error: linker command failed with exit code 1 (u e -v to  ee invocation) [macos-Debug, macos-Release]
Compiler Warnings (6)
../../../ThirdParty/SDL2/src/joystick/hidapi/SDL_hidapi_steam.c:165:9: warning: 'printf' macro redefined [-Wmacro-redefined] [linux-clang-Release]
../SparkEngine/Source/Engine/Animation/BlendSpace.cpp:313:16: warning: variable 'validTriCount' set but not used [-Wunused-but-set-variable] [linux-clang-Release]
../SparkEngine/Source/Physics/PhysicsBodyImpl.cpp:270:23: warning: comparing floating point with == or != is unsafe [-Wfloat-equal] [linux-clang-Release]
../SparkEngine/Source/Physics/PhysicsSystem.cpp:401:12: warning: use of old-style cast [-Wold-style-cast] [linux-clang-Release]
../../Tests/TestReliableChannel.cpp:390:9: warning: variable 'retransmitCount' set but not used [-Wunused-but-set-variable] [linux-clang-Release]
../../Tests/TestSparkError.cpp:34:5: warning: ignoring return value of function declared with 'warn_unused_result' attribute [-Wunused-result] [linux-clang-Release]

Updated: 2026-04-18T01:22:59Z — this comment is updated in-place, not duplicated.

check-format job was failing on pre-existing `const &` vs `const&`
qualifier spacing in Utils/Expected.h (introduced by 6a6f098 before
this branch diverged). Purely cosmetic — no semantic change.
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage (GCC + lcov)

Utils/Result.h                                 | 100%    29| 0.0%  28|    -    0
Utils/RingBuffer.h                             | 142%    59| 0.0%  84|    -    0
Utils/ScheduledCallback.h                      |    -     0|    -   0|    -    0
Utils/ScopeGuard.h                             | 142%    36| 0.0%  51|    -    0
Utils/ScopedTimer.h                            |25.0%    12| 0.0%   3|    -    0
Utils/Serializer.h                             |86.2%    58| 0.0%  44|    -    0
Utils/ShaderServiceClient.cpp                  |12.2%    41| 0.0%   4|    -    0
Utils/ShaderServiceClient.h                    | 100%     1| 0.0%   1|    -    0
Utils/ShaderServiceProtocol.h                  |11.8%    68| 0.0%   8|    -    0
Utils/SparkConsole.cpp                         |27.2%   151| 0.0%  18|    -    0
Utils/SparkConsole.h                           | 100%     2| 0.0%   2|    -    0
Utils/SparkError.h                             |10.9%    55| 0.0%   6|    -    0
Utils/SplineMath.cpp                           |20.5%    39| 0.0%   5|    -    0
Utils/SplinePath.h                             |    -     0|    -   0|    -    0
Utils/StackTrace.h                             |10.8%    74| 0.0%   8|    -    0
Utils/StateMachine.h                           |85.9%    64| 0.0%  49|    -    0
Utils/StringUtils.h                            |18.1%   116| 0.0%  21|    -    0
Utils/Telemetry.h                              |20.6%   136| 0.0%  23|    -    0
Utils/ThreadDebugger.h                         |11.6%   199| 0.0%  23|    -    0
Utils/ThreadSafeQueue.h                        |27.5%    40| 0.0%  11|    -    0
Utils/Timer.cpp                                |19.4%    36| 0.0%   7|    -    0
Utils/Timer.h                                  | 100%     2| 0.0%   2|    -    0
Utils/TimerManager.h                           |18.6%   102| 0.0%  19|    -    0
Utils/Tween.h                                  |26.3%    38| 0.0%   6|    -    0
Utils/UUID.h                                   |43.2%    37| 0.0%  16|    -    0
Utils/Validate.h                               |    -     0|    -   0|    -    0
Utils/WineDetection.cpp                        |23.1%    39| 0.0%   9|    -    0

[/home/runner/work/SparkEngine/SparkEngine/SparkSDK/Include/Spark/]
IEngineContext.h                               |7300%     1| 0.0%   1|    -    0
ServiceInterfaces.h                            | 200%     3| 0.0%   3|    -    0
Version.h                                      |    -     0|    -   0|    -    0
================================================================================
                                         Total:|30.7% 34599| 0.0%  6k|    -    0

Per-Subsystem Coverage

Subsystem Lines Hit Coverage Threshold Status
AI 3716 942 25.3% 35%
Animation 905 277 30.6% 35%
Audio 0 0 0% 30%
Camera 0 0 0% 40%
Core 4885 2918 59.7% 40%
ECS 426 213 50% 40%
Editor 7411 3046 41.1% 25%
GameModules 6621 3231 48.8% 30%
Graphics 17333 8600 49.6% 30%
Networking 3554 2351 66.2% 35%
Physics 0 0 0% 35%
Scripting 283 80 28.3% 30%
Utils 9778 6050 61.9% 60%

Total: 50.5% (27708/54912 lines)

Two real bugs flagged by the Codex automated review.

1. SeamlessAreaManager — strict-weak-ordering violation in load sort
   `DirectionalEffectiveDistance()` read m_playerPosition / m_playerVelocity
   under the player mutex on every comparator call. Because SetPlayerState()
   may be invoked from physics/gameplay threads, the player snapshot can
   change mid-sort, breaking std::sort's strict-weak-ordering requirement
   and producing nondeterministic load ordering or undefined behaviour.

   Fix: snapshot position+direction once per Update tick via the new
   SnapshotPlayerDirection() helper, build a Candidate{id, priority,
   effectiveDistance} array up-front, and sort that array with a pure
   comparator that no longer touches live state.

2. VolumetricClouds — horizontal rays starting inside the cloud slab
   were silently dropped. The slabDist() helper returned -1 whenever
   |dirY| < 1e-4, so a lateral ray (e.g. flying through cumulus at
   altitude) reported full transmittance and zero luminance, even when
   its origin was clearly between baseAltitude and topAltitude.

   Fix: detect the |dirY| ≈ 0 case explicitly. If origin is inside the
   slab, march [0, maxDistance]; if outside, early-out as before.

Two new regression tests cover the horizontal-ray paths
(HorizontalRayInsideSlab + HorizontalRayOutsideSlab). Full suite:
5616/5616 passing.
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage (GCC + lcov)

Utils/Result.h                                 | 100%    29| 0.0%  28|    -    0
Utils/RingBuffer.h                             | 142%    59| 0.0%  84|    -    0
Utils/ScheduledCallback.h                      |    -     0|    -   0|    -    0
Utils/ScopeGuard.h                             | 142%    36| 0.0%  51|    -    0
Utils/ScopedTimer.h                            |25.0%    12| 0.0%   3|    -    0
Utils/Serializer.h                             |86.2%    58| 0.0%  44|    -    0
Utils/ShaderServiceClient.cpp                  |12.2%    41| 0.0%   4|    -    0
Utils/ShaderServiceClient.h                    | 100%     1| 0.0%   1|    -    0
Utils/ShaderServiceProtocol.h                  |11.8%    68| 0.0%   8|    -    0
Utils/SparkConsole.cpp                         |27.2%   151| 0.0%  18|    -    0
Utils/SparkConsole.h                           | 100%     2| 0.0%   2|    -    0
Utils/SparkError.h                             |10.9%    55| 0.0%   6|    -    0
Utils/SplineMath.cpp                           |20.5%    39| 0.0%   5|    -    0
Utils/SplinePath.h                             |    -     0|    -   0|    -    0
Utils/StackTrace.h                             |10.8%    74| 0.0%   8|    -    0
Utils/StateMachine.h                           |85.9%    64| 0.0%  49|    -    0
Utils/StringUtils.h                            |18.1%   116| 0.0%  21|    -    0
Utils/Telemetry.h                              |20.6%   136| 0.0%  23|    -    0
Utils/ThreadDebugger.h                         |11.6%   199| 0.0%  23|    -    0
Utils/ThreadSafeQueue.h                        |27.5%    40| 0.0%  11|    -    0
Utils/Timer.cpp                                |19.4%    36| 0.0%   7|    -    0
Utils/Timer.h                                  | 100%     2| 0.0%   2|    -    0
Utils/TimerManager.h                           |18.6%   102| 0.0%  19|    -    0
Utils/Tween.h                                  |26.3%    38| 0.0%   6|    -    0
Utils/UUID.h                                   |43.2%    37| 0.0%  16|    -    0
Utils/Validate.h                               |    -     0|    -   0|    -    0
Utils/WineDetection.cpp                        |23.1%    39| 0.0%   9|    -    0

[/home/runner/work/SparkEngine/SparkEngine/SparkSDK/Include/Spark/]
IEngineContext.h                               |7300%     1| 0.0%   1|    -    0
ServiceInterfaces.h                            | 200%     3| 0.0%   3|    -    0
Version.h                                      |    -     0|    -   0|    -    0
================================================================================
                                         Total:|30.7% 34604| 0.0%  6k|    -    0

Per-Subsystem Coverage

Subsystem Lines Hit Coverage Threshold Status
AI 3716 942 25.3% 35%
Animation 905 277 30.6% 35%
Audio 0 0 0% 30%
Camera 0 0 0% 40%
Core 4885 2918 59.7% 40%
ECS 426 213 50% 40%
Editor 7411 3046 41.1% 25%
GameModules 6621 3231 48.8% 30%
Graphics 17335 8603 49.6% 30%
Networking 3554 2351 66.2% 35%
Physics 0 0 0% 35%
Scripting 283 80 28.3% 30%
Utils 9778 6050 61.9% 60%

Total: 50.5% (27711/54914 lines)

claude added 2 commits April 18, 2026 00:27
build-linux-clang (Release) has been failing with:
  /usr/bin/ld: ../lib/libJolt.a: error adding symbols: file format not recognized
  clang++: error: linker command failed with exit code 1

Root cause: actions/cache restores a build/ directory from a previous
run. When apt-get upgrades clang / binutils between runs, the cached
libJolt.a can end up in a format the current linker no longer
recognizes — similar to the existing PCH-vs-unistd_64.h mtime mismatch
that this job already handles.

Extend the existing stale-artifact cleanup to also scan lib*.a
archives. Each one is probed with \`ar t\`; any archive that can't be
listed is purged, forcing CMake to rebuild it on the next step.
ccache still keeps .o compilation fast.

Pre-existing failure (also hit PR #490 on the same job); fixed here.
Two pre-existing failures that were already present on PR #490 / Working:

1. NetworkStack_UDPInitializeSucceeds on Windows
   `UDPTransport::Initialize()` called ::socket() without calling
   WSAStartup() — on Windows that fails with WSANOTINITIALISED. The
   only call to WSAStartup() lived inside `NetworkManager::Initialize()`,
   so any test or subsystem creating a bare NetworkStack / UDPTransport
   couldn't open a socket.

   Fix: add a reference-counted `WinsockScope` RAII helper inside
   UDPTransport.h (Windows-only). Each UDPTransport takes one reference
   in Initialize() and releases it in Shutdown(); the first scope calls
   WSAStartup, the last calls WSACleanup.

2. build-macos (Debug/Release) — same `libJolt.a: error adding symbols:
   file format not recognized` as linux-clang. apt-get / brew upgrades
   leave stale archives in actions/cache, which the current ld can't
   parse. Extended the build step with the same `ar t`-based probe +
   rm that we just added to linux-clang.

Local: 5616/5616 tests pass, including the now-portable
NetworkStack_UDPInitializeSucceeds.
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage (GCC + lcov)

Utils/Result.h                                 | 100%    29| 0.0%  28|    -    0
Utils/RingBuffer.h                             | 142%    59| 0.0%  84|    -    0
Utils/ScheduledCallback.h                      |    -     0|    -   0|    -    0
Utils/ScopeGuard.h                             | 142%    36| 0.0%  51|    -    0
Utils/ScopedTimer.h                            |25.0%    12| 0.0%   3|    -    0
Utils/Serializer.h                             |86.2%    58| 0.0%  44|    -    0
Utils/ShaderServiceClient.cpp                  |12.2%    41| 0.0%   4|    -    0
Utils/ShaderServiceClient.h                    | 100%     1| 0.0%   1|    -    0
Utils/ShaderServiceProtocol.h                  |11.8%    68| 0.0%   8|    -    0
Utils/SparkConsole.cpp                         |27.2%   151| 0.0%  18|    -    0
Utils/SparkConsole.h                           | 100%     2| 0.0%   2|    -    0
Utils/SparkError.h                             |10.9%    55| 0.0%   6|    -    0
Utils/SplineMath.cpp                           |20.5%    39| 0.0%   5|    -    0
Utils/SplinePath.h                             |    -     0|    -   0|    -    0
Utils/StackTrace.h                             |10.8%    74| 0.0%   8|    -    0
Utils/StateMachine.h                           |85.9%    64| 0.0%  49|    -    0
Utils/StringUtils.h                            |18.1%   116| 0.0%  21|    -    0
Utils/Telemetry.h                              |20.6%   136| 0.0%  23|    -    0
Utils/ThreadDebugger.h                         |11.6%   199| 0.0%  23|    -    0
Utils/ThreadSafeQueue.h                        |27.5%    40| 0.0%  11|    -    0
Utils/Timer.cpp                                |19.4%    36| 0.0%   7|    -    0
Utils/Timer.h                                  | 100%     2| 0.0%   2|    -    0
Utils/TimerManager.h                           |18.6%   102| 0.0%  19|    -    0
Utils/Tween.h                                  |26.3%    38| 0.0%   6|    -    0
Utils/UUID.h                                   |43.2%    37| 0.0%  16|    -    0
Utils/Validate.h                               |    -     0|    -   0|    -    0
Utils/WineDetection.cpp                        |23.1%    39| 0.0%   9|    -    0

[/home/runner/work/SparkEngine/SparkEngine/SparkSDK/Include/Spark/]
IEngineContext.h                               |7300%     1| 0.0%   1|    -    0
ServiceInterfaces.h                            | 200%     3| 0.0%   3|    -    0
Version.h                                      |    -     0|    -   0|    -    0
================================================================================
                                         Total:|30.7% 34605| 0.0%  6k|    -    0

Per-Subsystem Coverage

Subsystem Lines Hit Coverage Threshold Status
AI 3716 942 25.3% 35%
Animation 905 277 30.6% 35%
Audio 0 0 0% 30%
Camera 0 0 0% 40%
Core 4885 2918 59.7% 40%
ECS 426 213 50% 40%
Editor 7411 3046 41.1% 25%
GameModules 6621 3232 48.8% 30%
Graphics 17335 8603 49.6% 30%
Networking 3554 2351 66.2% 35%
Physics 0 0 0% 35%
Scripting 283 80 28.3% 30%
Utils 9778 6050 61.9% 60%

Total: 50.5% (27712/54914 lines)

Previous attempt with `ar t` probe was insufficient — `ar t` only lists
archive member names and succeeds on archives whose embedded .o files
have wrong object format. The linker then still fails with
"file format not recognized" on the stale archive.

Simpler and actually-correct fix: delete every lib*.a from the restored
build/ directory. CMake re-links them from .o files that come straight
out of ccache, so the extra cost is a couple of seconds of archiving.

Applied to both build-linux-clang and build-macos.
@Krilliac
Krilliac merged commit 7062ab7 into Working Apr 18, 2026
36 of 42 checks passed
@Krilliac
Krilliac deleted the claude/evaluate-engine-features-94eP0 branch April 18, 2026 06:11
@github-actions

Copy link
Copy Markdown
Contributor

Code Coverage (GCC + lcov)

Utils/Result.h                                 | 100%    29| 0.0%  28|    -    0
Utils/RingBuffer.h                             | 142%    59| 0.0%  84|    -    0
Utils/ScheduledCallback.h                      |    -     0|    -   0|    -    0
Utils/ScopeGuard.h                             | 142%    36| 0.0%  51|    -    0
Utils/ScopedTimer.h                            |25.0%    12| 0.0%   3|    -    0
Utils/Serializer.h                             |86.2%    58| 0.0%  44|    -    0
Utils/ShaderServiceClient.cpp                  |12.2%    41| 0.0%   4|    -    0
Utils/ShaderServiceClient.h                    | 100%     1| 0.0%   1|    -    0
Utils/ShaderServiceProtocol.h                  |11.8%    68| 0.0%   8|    -    0
Utils/SparkConsole.cpp                         |27.2%   151| 0.0%  18|    -    0
Utils/SparkConsole.h                           | 100%     2| 0.0%   2|    -    0
Utils/SparkError.h                             |10.9%    55| 0.0%   6|    -    0
Utils/SplineMath.cpp                           |20.5%    39| 0.0%   5|    -    0
Utils/SplinePath.h                             |    -     0|    -   0|    -    0
Utils/StackTrace.h                             |10.8%    74| 0.0%   8|    -    0
Utils/StateMachine.h                           |85.9%    64| 0.0%  49|    -    0
Utils/StringUtils.h                            |18.1%   116| 0.0%  21|    -    0
Utils/Telemetry.h                              |20.6%   136| 0.0%  23|    -    0
Utils/ThreadDebugger.h                         |11.6%   199| 0.0%  23|    -    0
Utils/ThreadSafeQueue.h                        |27.5%    40| 0.0%  11|    -    0
Utils/Timer.cpp                                |19.4%    36| 0.0%   7|    -    0
Utils/Timer.h                                  | 100%     2| 0.0%   2|    -    0
Utils/TimerManager.h                           |18.6%   102| 0.0%  19|    -    0
Utils/Tween.h                                  |26.3%    38| 0.0%   6|    -    0
Utils/UUID.h                                   |43.2%    37| 0.0%  16|    -    0
Utils/Validate.h                               |    -     0|    -   0|    -    0
Utils/WineDetection.cpp                        |23.1%    39| 0.0%   9|    -    0

[/home/runner/work/SparkEngine/SparkEngine/SparkSDK/Include/Spark/]
IEngineContext.h                               |7300%     1| 0.0%   1|    -    0
ServiceInterfaces.h                            | 200%     3| 0.0%   3|    -    0
Version.h                                      |    -     0|    -   0|    -    0
================================================================================
                                         Total:|30.7% 34605| 0.0%  6k|    -    0

Per-Subsystem Coverage

Subsystem Lines Hit Coverage Threshold Status
AI 3716 942 25.3% 35%
Animation 905 277 30.6% 35%
Audio 0 0 0% 30%
Camera 0 0 0% 40%
Core 4885 2918 59.7% 40%
ECS 426 213 50% 40%
Editor 7411 3046 41.1% 25%
GameModules 6621 3232 48.8% 30%
Graphics 17335 8603 49.6% 30%
Networking 3554 2351 66.2% 35%
Physics 0 0 0% 35%
Scripting 283 80 28.3% 30%
Utils 9778 6050 61.9% 60%

Total: 50.5% (27712/54914 lines)

Krilliac pushed a commit that referenced this pull request Apr 18, 2026
Root cause of the linux-clang-Release / macos-{Debug,Release} linker
failures on PR #491 was NOT a stale CI cache — a fresh local build
reproduced it. Extracting any member of build/lib/libJolt.a showed
LLVM IR bitcode, not ELF. GNU ld / ld64 then rejects the archive with:

    libJolt.a: error adding symbols: file format not recognized
    clang++: error: linker command failed with exit code 1

Jolt's CMake wrapper was forcing `INTERPROCEDURAL_OPTIMIZATION=ON`
whenever CMAKE_BUILD_TYPE was Release/MinSizeRel/RelWithDebInfo,
regardless of the top-level `ENABLE_LTO` option. The linux-clang CI
passes `-DENABLE_LTO=OFF` expecting native objects everywhere, but
Jolt still produced bitcode — a classic ABI/format mismatch that only
the thin-LTO-aware lld or llvm-ar can resolve.

Fix:
- CMakeLists.txt: gate Jolt's IPO on `ENABLE_LTO AND <release config>`
  so the engine and Jolt stay in the same object format.
- build.yml: add `-DENABLE_LTO=OFF` to the macOS job. The job already
  unconditionally purges `lib*.a` as a workaround — removing the
  underlying mismatch lets that step become a no-op.

Verified locally: after the fix, `ar x libJolt.a AABBTreeBuilder.cpp.o`
yields ELF relocatable instead of LLVM IR bitcode.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants