Skip to content

Enable compressonator-bc7e on macOS - #3

Draft
JorgeVV wants to merge 2 commits into
noisethanks:masterfrom
JorgeVV:feat/compressonator-bc7e-macos
Draft

JorgeVV wants to merge 2 commits into
noisethanks:masterfrom
JorgeVV:feat/compressonator-bc7e-macos

Conversation

@JorgeVV

@JorgeVV JorgeVV commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Makes the compressonator-bc7e backend available on macOS. It was hard-gated off because no darwin build of the fork existed — §8 of the fork's README lists macOS as out of scope, and its v1.0.0 release ships Linux and Windows binaries only.

Companion PR: noisethanks/compressonator#1 — the build script and the source fixes that make a macOS binary possible. Merge that one first; this PR embeds its output.

What ships here

internal/tools/bin/compressonator-bc7e-macos — universal (x86_64 + arm64), ad-hoc signed like texconv-macos and 7zz-macos, 6.1 MB. Everything else is un-gating: embed_darwin.go embeds it, config.normalizeBackend stops coercing darwin to texconv, and the Settings row becomes visible. Availability still keys off EmbeddedTools.CompressonatorPath == "" rather than runtime.GOOS.

Native Apple Silicon releases

Second commit. The release built darwin/amd64 only, so every Apple Silicon user who downloaded a release ran under Rosetta 2 — and so did every embedded tool, because a universal child process inherits the parent's slice. Verified directly:

parent universal child runs as
arm64 arm64
x86-64 x86-64

So texconv-macos, 7zz-macos and the new compressonator-bc7e-macos were all translated despite shipping native arm64 code. macOS now ships two archives:

  • atak-<version>-macos-x64.tar.gz
  • atak-<version>-macos-arm64.tar.gz

Two archives rather than one universal binary: the tools are embedded per GOOS and each already carries both slices, so a universal atak would hold two complete copies at ~45 MB against the 25 MB target. Each single-arch build is 22 MB (9.2 MB compressed). Verified with a full goreleaser release --snapshot — four binaries, four archives, correct names, Mach-O 64-bit executable arm64 inside the arm64 tarball.

Tests now run on macOS

dispatch_srgb_test.go and e2e_srgb_summary_test.go hardcoded /home/abhi/... paths and skipped on every other machine. They now resolve the binary from internal/tools/bin for the current platform, so TestDispatchCompressonatorSrgbFallback exercises the compressonator → texconv fallback on macOS and passes.

Verification (Apple Silicon, M4 Max)

Check Result
Format sweep, both slices 38/40 configs; the 2 failures are sources already in the destination format, identical on both slices
Real GAMMA textures, uncompressed sources 38/39 (ATAK skips compressed sources at scan time, so this is the real input)
End to end via tools.Extract + RunPool 12/12, byte-identical across two full runs
Quality vs stock BC7 within ±0.7 dB either way
Speed vs stock BC7 at -Quality 1.0 0.54 s vs 24.70 s, ~46×

Caveats worth reviewing

  1. Cross-platform output is no longer bit-identical. The arm64 slice differs in the low bits from the x86-64 builds on 18 of 38 configs, at equal PSNR. Output stays reproducible within a slice. SPEC.md says so explicitly; the previous "bit-identical output" claim was reworded rather than quietly dropped.
  2. Release size: macOS goes ~17 MB → ~22 MB per architecture, now the tightest of the three against the 25 MB ceiling.
  3. .goreleaser.yaml still uses archives.format and archives.builds, both deprecated. That is pre-existing — I matched the file's existing style rather than mixing dialects — but the workflow pins version: latest, so a future goreleaser release could break it. Worth a separate cleanup.

Not changed, on purpose

One real texture in the sample fails with unsupported input image file format, which does not match the narrow Could not load source file fallback pattern, so no texconv retry happens. That behaviour is pre-existing and identical on all platforms, so widening the matcher did not belong in this PR.

Builds the compressonator-bc7e fork for macOS and removes the darwin
gates, so the backend is selectable on all three platforms.

Binary:
- internal/tools/bin/compressonator-bc7e-macos — universal (x86_64 +
  arm64), ad-hoc signed like texconv-macos and 7zz-macos, 6.1MB.
- Built from noisethanks/compressonator @ bc7enc-rdo-integration with
  tools/macos/build_flavor.sh. See the companion PR on that repo.

Un-gating:
- embed_darwin.go embeds the binary and names it compressonatorcli.
- config.normalizeBackend no longer coerces darwin to texconv.
- The Settings row is visible on darwin, and save() no longer overrides
  the selection.
- Availability still keys off EmbeddedTools.CompressonatorPath == ""
  rather than runtime.GOOS, so a platform without a build needs no
  changes outside embed_<platform>.go.

Tests:
- dispatch_srgb_test.go and e2e_srgb_summary_test.go resolve the tool
  binary from internal/tools/bin for the platform running the test,
  replacing hardcoded /home/abhi paths that skipped everywhere else.
  TestDispatchCompressonatorSrgbFallback now runs on macOS and passes,
  so the compressonator -> texconv fallback is covered there.

Verified on Apple Silicon:
- 38 of 40 format x mip configs encode on both slices. The 2 failures
  are sources already in the destination format, and fail identically
  on both.
- 38 of 39 uncompressed real GAMMA textures encode. ATAK skips
  compressed sources during the scan, so that is the input the backend
  actually sees.
- 12 of 12 real textures through tools.Extract and RunPool, byte
  identical across two full runs.
- bc7e matches stock BC7 quality within 0.7dB either way and runs 46x
  faster at -Quality 1.0 (0.54s against 24.70s for three textures).

Cross-platform output is no longer bit-identical: the arm64 slice
differs in the low bits from the x86-64 builds on 18 of 38 configs, at
equal PSNR. Output stays reproducible within a slice.

SPEC.md gains a "Building compressonator-bc7e for macOS" section for the
build recipe, the ISPC host trap that silently corrupts BC7 output, and
the upstream defects the fork now carries. Release size ceiling updated:
macOS is now the tightest at ~22MB.
The release built darwin/amd64 only, so every Apple Silicon user who
downloaded a release ran atak under Rosetta 2 — and with it every
embedded tool, because a universal child process inherits the parent's
slice. Verified directly: an arm64 parent spawning a universal child
gets arm64, an x86-64 parent spawning the same child gets x86-64. So
texconv, 7zz and compressonator-bc7e were all translated despite
shipping native arm64 code.

macOS now ships two archives, atak-<version>-macos-x64.tar.gz and
atak-<version>-macos-arm64.tar.gz, and the release notes list both.

Two archives rather than one universal binary: the tools are embedded
per GOOS and each already carries both slices, so a universal atak would
hold two complete copies at roughly 45MB, against the 25MB target. Each
single-architecture build is 22MB.
elseform added a commit to elseform/atak that referenced this pull request Aug 12, 2026
elseform added a commit to elseform/atak that referenced this pull request Aug 12, 2026
Resolved conflicts on config.go, embed_darwin.go, settings.go, and the
compressonator-bc7e-macos binary in favor of PR noisethanks#3's already-merged
versions — feat/improved-autodetection's ancestry predates PR noisethanks#3 and
still carried the old pre-PR#3 backend code on those files, but its
only actual unique content is welcome.go's auto-detection logic, which
merged clean.
elseform added a commit to elseform/atak that referenced this pull request Aug 12, 2026
…v rebuild

Both fixes previously landed as direct dev commits (never on a source
branch), so rebuilding dev from PR noisethanks#3 + feature branches lost them:

- settingsFieldLabel was missing entries for the per-category/per-mod
  toggle fields again (same root cause as before: feat/per-category and
  settings-scroll each only know about their own fields)
- BuildVirtualFS's wrapper-folder path anchoring (mods shipping content
  under an extra top-level folder instead of at the mod root)
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