Patch Notes 0.3.1 to 0.3.4

MayaFlux 0.3.1

26th April 2026

Targets removal of deprecated creational API and correctness fix in the Lila JIT compiler subsystem.

Fixes

Lila FreeType include path injection

ClangInterpreter was missing the -isystem flag for FreeType headers, causing runtime evaluation of code including <ft2build.h> to fail with unresolved dependencies. The JIT compiler now mirrors the existing Eigen include injection pattern, resolving the path via Config::FREETYPE_HINT (populated at configure time from find_package(Freetype)) with fallback to well-known system paths in HostEnvironment. Live coding workflows using Portal text rendering can now evaluate user code without manual include path specification.

Breaking Changes

Removal of CreationProxy and pipe operator overloads

CreationProxy<T>, PendingChannel<T>, and all operator| overloads for domain binding have been removed. This was announced at 0.3.0 and documented throughout the 0.3 development cycle.

Migrate all call sites from the deprecated bracket-pipe syntax to the committed pipe-bracket syntax:

// Old (removed)
object[ch] | Audio
object[{0,1}] | Audio

// New (required)
object | Audio[ch]
object | Audio[{0,1}]

Creator methods now return std::shared_ptr<T> directly without intermediary proxy objects. The domain binding is resolved at the call site via DomainSpec::operator[].

Removed symbols:

  • CreationProxy<T>
  • PendingChannel<T>
  • operator|(shared_ptr<Node>, Domain) and typed variants
  • operator|(PendingChannel<T>, CreationContext)
  • All MAYAFLUX_API Domain operator| declarations

Upgrade Notes

Not a drop-in replacement. Any code using the bracket-pipe syntax ([ch] | Audio) must be migrated to pipe-bracket syntax (| Audio[ch]) before compilation. The upgrade is mechanical: swap the order of the bracket and pipe operators, keeping the channel argument within the brackets.

No functional changes to committed systems. The DomainSpec pipe syntax and channel binding semantics remain stable.

Commit Summary

See full diff: Github

91c96da8b prepare for 0.3.1 release
5962cec00 fix(Lila): inject FreeType include path into JIT compiler flags
e14d29ab2 refactor(API): remove CreationProxy, PendingChannel, and Domain operator| overloads (0.3.1)

MayaFlux 0.3.2

1st May 2026

Targets correctness bugs in mesh loading, engine lifecycle, GLFW platform selection, and Linux shutdown semantics.

Fixes

MeshNetworkBuffer texture binding collision

Per-slot diffuse textures in MeshNetworkBuffer were bound at binding=2+i, colliding with the slotIndices SSBO already occupying binding=2 in set=0. The descriptor set reported a type mismatch (STORAGE_BUFFER vs COMBINED_IMAGE_SAMPLER) and crashed on the first textured model load. Per-slot texture bindings have been moved to binding=3+i, reserving binding=2 exclusively for the slotIndices buffer. set=0, binding=0 remains reserved for the engine-owned ViewTransform UBO.

MeshNetworkProcessor geometry upload on attachment

MeshNetworkProcessor::on_attach called upload_combined against an unsorted sorted_indices vector, cleared all dirty flags, and then never uploaded geometry on subsequent frames because rebuild_sort() was lazy and only fires inside process_batch. Added ensure_sorted() to MeshNetwork and call it at the top of on_attach to guarantee slot order before the first GPU upload.

Engine initialization state conflation

is_engine_initialized tracked two distinct concerns: whether Init() has completed and managers are ready, and whether the engine is actively processing. Split into is_engine_configured (Init() succeeded, managers ready) and the existing is_running() (actively processing). Added Engine::is_configured(), Core::is_configured(), and public API is_engine_configured(). All internal call sites updated to query the appropriate state.

GLFW platform hint resolution

force_x11_on_wayland resolution was a separate pre-pass before platform hint application, leaving the hint unapplied when the sentinel matched. Folded resolution into the existing platform switch in configure(). GLFW_ANY_PLATFORM is now the sentinel for “do not hint”; the hint is only applied when a non-default platform is resolved. Default behaviour (no forced platform) is unchanged.

Linux shutdown gate robustness

The engine shutdown gate on Linux used std::cin.get(), which blocks indefinitely in headless contexts (GUI launchers, capture tools) and returns immediately on EOF (piped input), making graceful shutdown impossible in those environments. Replaced with a sigaction/select loop: TTY contexts block on select and exit on Return or signal; non-TTY contexts block on sigsuspend until SIGINT or SIGTERM. Static atomic reset on entry handles engine recreation in the same process.

Upgrade Notes

No API changes. Drop-in replacement for 0.3.1. The is_engine_initialized query remains available but should be migrated to is_engine_configured() if initialization state distinction is relevant; is_running() covers the active processing case.

Commit Summary

See full diff: Github

946717a81 prepare for 0.3.2 release
7df1cd1d3 fix(engine): robust shutdown gate for Linux across terminal and headless contexts
fe491465d fix(windowing): resolve GLFW platform hint before applying in configure()
1a72d8c4e refactor: separate engine configuration state from runtime state
356a88bc4 fix(MeshNetworkBuffer): move per-slot texture bindings from binding=2 to binding=3
d41eae286 fix(MeshNetworkProcessor): ensure slot sort order before first GPU upload in on_attach

MayaFlux 0.3.3

5th May 2026

Unifies temporal channel binding with DomainSpec and fixes library installation paths on multi-lib systems.

Breaking Changes

Temporal channel binding unified with DomainSpec

Time() now takes duration only. Channel binding moves to the domain site via DomainSpec::operator[], consistent with Creator methods introduced in 0.3.1.

// Old (removed)
node   >> Time(2.0, 0) | Audio;
node   >> Time(2.0, {0, 1}) | Audio;
buffer >> Time(2.0, 0) | Audio;

// New (required)
node   >> Time(2.0) | Audio[0];
node   >> Time(2.0) | Audio[{0, 1}];
buffer >> Time(2.0) | Audio[0];
net    >> Time(2.0) | Graphics;

Removed symbols:

  • TimeSpec::channels field
  • Time(double, uint32_t) constructor
  • Time(double, vector<uint32_t>) constructor
  • operator| overloads taking Domain in Temporal.hpp/cpp

Changed:

  • operator| overloads in Temporal now take const CreationContext& instead of Domain
  • Channel extraction moves from spec.channels to ctx.channel / ctx.channels
  • Temporal.hpp replaces #include "Domain.hpp" with #include "Creator.hpp" to gain CreationContext, DomainSpec, Audio, and Graphics

This completes the DomainSpec unification announced at 0.3.0, deprecated in previous versions, and documented in all release notes. Temporal scheduling now aligns with the committed pipe-bracket syntax across all domains.

Fixes

CMake installation paths on multi-lib systems

Hardcoded lib install paths in install.cmake and MayaFluxConfig.cmake.in were incompatible with Fedora and other distributions using lib64 for 64-bit libraries. Replaced with CMAKE_INSTALL_LIBDIR, which resolves correctly across all GNU install directory conventions. Removes the manual mv workaround from packaging specs.

Upgrade Notes

Not a drop-in replacement. Any code using Time(seconds, channel) or Time(seconds, {channels}) must migrate to Time(seconds) | Audio[...] before compilation. The upgrade is mechanical: extract the channel argument, move it after the pipe, and wrap it in brackets with the domain.

Library installation now targets lib64 on 64-bit Fedora/RHEL systems without manual correction.

Commit Summary

See full diff: Github

d5f2f28f7 Prepare for 0.3.3 release.
ee1a8ca75 refactor(api): unify Temporal channel binding with DomainSpec
d267d523b fix(cmake): use GNUInstallDirs for lib directory resolution

MayaFlux 0.3.4

7th May 2026

Targets correctness fixes in operator token release and ResonatorNetwork output, CMake library path resolution, operator shutdown safety, and operator collection access patterns. Adds parameterized path generation and operator accessors for external coroutine integration.

Fixes

PhysicsOperator and TopologyOperator token release

PhysicsOperator::add_collection and TopologyOperator::add_topology acquired m_access_token via CAS spin but never released it, causing subsequent process() calls to spin forever. Added store(0) after each push_back to release the token.

ResonatorNetwork output mode and shadowed buffer

ResonatorNetwork defaulted to OutputMode::NONE at construction, causing Creator::register_network to fire a spurious warning and rely on the forced-AUDIO_SINK path. Set AUDIO_SINK explicitly in both constructors.

ResonatorNetwork declared a duplicate m_last_audio_buffer member shadowing the base class NodeNetwork field in the protected section. The shadow caused apply_output_scale() and get_audio_buffer() to operate on different vectors, producing incorrect output and potential memory corruption at scale. Removed the duplicate declaration.

Operator shutdown hang on access token spin

The CAS spin on m_access_token in PathOperator, TopologyOperator, and PhysicsOperator had no exit path on engine shutdown, causing the graphics thread to hang indefinitely if destruction occurred while a spin was in progress. Added std::atomic<bool> m_shutdown to each operator. The destructor sets it with release ordering; the spin loop checks it with relaxed ordering on each failed CAS and returns immediately if set. The relaxed check is correct because the destructor’s release store establishes the required happens-before relationship.

CMake library path resolution on non-Fedora installs

CMAKE_INSTALL_LIBDIR expands to a relative segment (“lib”) on most platforms and an absolute path ("/usr/lib64") on Fedora only. Relative paths caused IMPORTED_LOCATION to resolve relative to the build directory rather than the install root. Guarded with IS_ABSOLUTE: if relative, prepend PACKAGE_PREFIX_DIR to produce the correct absolute path. Fedora’s absolute path is left unchanged. No platform branching required.

Features

Parameterized path generation

PathOperator::add_path previously hardcoded 1024 max control points and forwarded the operator’s default samples per segment. Callers can now configure per-path capacity and interpolation parameters directly via new optional arguments. initialize and initialize_paths updated to forward m_default_samples_per_segment.

Operator collection accessors

Added get_path and get_topology accessors on operator collections, exposing indexed access to PathGeneratorNode and TopologyGeneratorNode instances. External coroutines can now call add_control_point and set_points directly without routing through the network layer.

TopologyOperator samples-per-segment dispatch

Added typed set_samples_per_segment on TopologyOperator forwarding to all topology nodes. PointCloudNetwork::set_samples_per_segment now dispatches to both PathOperator and TopologyOperator rather than warning on topology mode.

Operator vertex count aggregate

PathOperator, TopologyOperator, and PhysicsOperator were returning the vertex count from collection 0 only in get_vertex_layout. With NetworkGeometryBuffer driving the draw call directly from the layout, the count must reflect the full aggregate across all collections.

Nexus MouseTrigger capture safety

Wiring is a temporary builder destroyed after finalise(). The MouseTrigger lambda previously captured [this, id], leaving a dangling reference to the builder. Snapshot m_fabric and m_entity_id into named locals before the lambda to outlive the builder lifetime.

CompositeGeometryBuffer public registration

Added forward declaration and ALL_BUFFER_REGISTRATION entry for CompositeGeometryBuffer alongside the include in MayaFlux.hpp, enabling proxy-based instantiation.

Upgrade Notes

No API changes. Drop-in replacement for 0.3.3.

New optional parameters on PathOperator::add_path are backward compatible; existing calls without them use operator defaults as before. New accessors and dispatch methods are additive.

Commit Summary

See full diff: Github

e2ad692d5 prepare for 0.3.4 release
777c63b31 fix: operator token release, ResonatorNetwork output mode, shadow buffer
c951d177b fix(cmake): resolve relative CMAKE_INSTALL_LIBDIR for non-Fedora installs
259addd10 fix(operators): add shutdown guard to access token spin in PathOperator, TopologyOperator, PhysicsOperator
b6cf200ff feat(operators): atomic access token for collection mutation in PathOperator, TopologyOperator, PhysicsOperator
68d6aa576 feat(nodes): expose samples_per_segment, max_control_points and tension on add_path
04df085dd fix(nodes): set aggregate vertex_count on get_vertex_layout for collection operators
72309935e fix(nexus): capture Fabric by ref and entity id by value in MouseTrigger lambda
c3af0fb06 feat(nodes): extend set_samples_per_segment to TopologyOperator
35347dbe2 feat(nodes): add get_path and get_topology accessors on operator collections
3ccccfed6 feat(buffers): register CompositeGeometryBuffer in proxy registry and public header