Skip to content

[FEATURE] Enable the planar NEON WaveNet engine (AArch64 / Apple Silicon / ARMv7) - #679

Open
rikkus wants to merge 4 commits into
sdatkinson:mainfrom
rikkus:fused-optimisation
Open

rikkus wants to merge 4 commits into
sdatkinson:mainfrom
rikkus:fused-optimisation

Conversation

@rikkus

@rikkus rikkus commented Sep 11, 2026

Copy link
Copy Markdown

Enables the planar NEON kernels (sdatkinson/NeuralAmpModelerCore#313) in plugin builds.

Verification

Verified on macOS (Apple Silicon): built via the official NeuralAmpModeler/scripts recipe's own toolchain steps (iPlug2/Dependencies/IPlug/download-iplug-sdks.sh, iPlug2/Dependencies/download-prebuilt-libs.sh, then xcodebuild ... -target VST3 / -target AU).

  • VST3 and AU targets both build clean (universal arm64+x86_64).
  • The planar kernel symbols (A2PlanarNano, A2PlanarFull) are present in the built binary (nm -C).
  • auval -v aufx 1YEo SDAaAU VALIDATION SUCCEEDED, including real audio-render tests at multiple block sizes (64/137/512/4096 frames) and sample rates (11025-192000 Hz), parameter get/set, MIDI, and channel-layout tests. All pass.

iOS and Windows are verified by project-file correctness only.

Checklist item Answer
VST3 passes unit tests Yesauval AU validation passed in full (stronger runtime check than the VST3 SDK's own test host, which needs building separately); VST3 target itself builds clean as a universal binary
VST3 passes unit tests — Windows Not tested — no Windows machine available
Adds/removes/renames plugin parameters? No
Adds/removes graphical assets? No

Submodule note

.gitmodules still points NeuralAmpModelerCore at sdatkinson/NeuralAmpModelerCore — that's not something this PR changes. But the pinned commit only exists on the fork (rikkus/OptimisationWorkOnNeuralAmpModelerCore) until Core PR #313 merges upstream, so a plain git submodule update --init against this branch will fail to fetch it in the meantime. To build/test locally before #313 merges:

SHA=$(git ls-tree HEAD NeuralAmpModelerCore | awk '{print $3}')
git -C NeuralAmpModelerCore fetch https://github.com/rikkus/OptimisationWorkOnNeuralAmpModelerCore.git "$SHA"
git -C NeuralAmpModelerCore checkout "$SHA"
git -C NeuralAmpModelerCore submodule update --init --recursive

Once #313 merges, a normal git submodule update --init against a future pin bump needs no special handling.

Point NeuralAmpModelerCore at rikkus/OptimisationWorkOnNeuralAmpModelerCore
(the armv7-a2-planar branch, head of sdatkinson/NeuralAmpModelerCore#313) and
wire the planar kernels into plugin builds. This replaces an earlier attempt
at enabling a different, now-retired engine ("fused"); that work is superseded
by the planar kernels and dropped here.

- macOS: swap wavenet/fused.{cpp,h} for wavenet/a2_planar.{cpp,h} in the Xcode
  project across all 8 native targets. NAM_ENABLE_A2_FAST was already defined
  here; no new build flag is needed, since a2_planar.h gates itself internally
  on NAM_ENABLE_A2_FAST plus the target being AArch64 or ARMv7 with NEON+FMA —
  the header declares nothing and the translation unit compiles to no symbols
  everywhere else.
- iOS: same swap, plus a fix -- the previous attempt gave a2_fast.cpp and
  fused.cpp the same UUID for both their PBXFileReference and PBXBuildFile
  entries, a duplicate-key bug that meant only one of the two was ever
  actually wired into the build. Re-added both a2_fast.{cpp,h} (this PR's
  iOS enablement, kept) and a2_planar.{cpp,h} with distinct UUIDs across all
  3 native targets. Also defines NAM_ENABLE_A2_FAST on iOS, which wasn't set
  before.
- Windows: a2_fast.cpp/h was already registered in the three .vcxproj files;
  added a2_planar.cpp/h alongside it the same way. NAM_ENABLE_FUSED (which had
  been added to NeuralAmpModeler-win.props without ever registering fused.cpp
  in any .vcxproj -- a build that would not have linked) is removed; nothing
  else changes since a2_fast was already there.
- All three platforms: also registered linear.{cpp,h}, nam_file.{cpp,h},
  sequential.{cpp,h} and the newly-referenced headers (compiler.h, container.h,
  model_config.h, slimmable.h, wavenet/detail.h, wavenet/params.h,
  wavenet/slimmable.h), none of which this project's Core submodule pin had
  reached before. Without these the build fails to link on
  nam::validate_nam_file -- unrelated to fused/planar, just Core having grown
  new files since this project was last synced, surfaced now because the
  submodule bump needed to pick up the planar kernels also picks up everything
  else Core has added since.
- .gitmodules points at the fork rather than upstream NeuralAmpModelerCore for
  now, since sdatkinson/NeuralAmpModelerCore#313 is not yet merged. Repoint to
  upstream once it lands.

Verified on macOS (Apple Silicon): VST3 and AU targets both build clean
(universal arm64+x86_64) from the official NeuralAmpModeler/scripts recipe's
own toolchain steps, the planar kernel symbols (A2PlanarNano/A2PlanarFull) are
present in the built binary, and `auval -v aufx 1YEo SDAa` passes in full,
including real audio-render tests at multiple block sizes and sample rates.
iOS and Windows are verified by project-file correctness only (no device/
Windows machine available here) -- same caveat as the PR this replaces.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rikkus and others added 2 commits September 11, 2026 16:24
The rebase behind sdatkinson/NeuralAmpModelerCore#313 had picked up
upstream's cached-prewarm optimisation to A2FastModel without adapting the
planar models to it, so the previous pin (d3814ad) fails Core's own
zero-allocation prewarm test. Follows that fix (d3814ad -> 552c5ab).

Verified: VST3 target rebuilds clean (universal arm64+x86_64) with this pin.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
A PR against this repo shouldn't propose changing where its own submodule is
fetched from -- that's not something to ship, even temporarily. The pinned
commit (552c5ab) still only exists on the fork
(rikkus/OptimisationWorkOnNeuralAmpModelerCore) until Core PR sdatkinson#313 merges
upstream, so a plain `git submodule update --init` against this branch will
fail to fetch it until then; see the PR description for the one-line
workaround to build and test locally in the meantime. Once sdatkinson#313 merges, the
next pin bump needs no special handling -- .gitmodules already points at the
right place.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
rikkus added a commit to rikkus/OptimisationWorkOnNeuralAmpModelerPlugin that referenced this pull request Sep 11, 2026
The fused engine this file described is retired, and the branches it pointed
new sessions at (optimise-for-apple-silicon) are gone. Describe what is live
instead: the planar kernels in Core PR sdatkinson#313, their plugin wiring in PR sdatkinson#679,
why the submodule URL stays upstream while the pin needs fetching from the
fork, how to build and test core and plugin, the known issues, and the
current branch layout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Core PR sdatkinson#313's parity test could not pass as wired: run_tests compiles all of
its sources at -O0, where GCC does not contract A2FastModel's 3-channel
`a * b + c` chain into an FMA, so the reference stopped being the code the
kernels reproduce. Fixed there by building the A2 kernels as an -O3 object
library for that target only (552c5ab -> 44412fa).

Core-side build config only -- the one file changed is Core's
tools/CMakeLists.txt, which the plugin's Xcode projects never read, so nothing
about this plugin's build changes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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.

1 participant