Skip to content

Add opt-in hardware cache for Animate bitmaps - #56

Open
Tutez64 wants to merge 2 commits into
openfl:masterfrom
Tutez64:optimize/animate-hardware-bitmap-cache
Open

Add opt-in hardware cache for Animate bitmaps#56
Tutez64 wants to merge 2 commits into
openfl:masterfrom
Tutez64:optimize/animate-hardware-bitmap-cache

Conversation

@Tutez64

@Tutez64 Tutez64 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Summary

This adds an opt-in swf_hardware_bitmap_cache define that allows Animate bitmap assets and compatible bitmap-filled shapes to discard their CPU-side image data after upload to the GPU.

The implementation:

  • reuses cached BitmapData for direct bitmap symbols;
  • detects whether shapes can be rendered entirely by the hardware backend;
  • keeps a separate readable cache for software-rendered and scale9 shapes;
  • calls disposeImage() only for hardware-compatible assets;
  • clears both caches when unloading the library.

The feature is opt-in because discarding the CPU-side image prevents later pixel access and makes context restoration impossible without reloading the asset. It should therefore only be enabled when these bitmaps are immutable GPU resources and a graphics-context loss can be handled externally.

Benchmark

SWFAnimateHardwareBitmapCacheRepro.zip
It loads 64 distinct 1024×1024 bitmap assets, creates four instances of each, and retains a large stable object graph to measure full-GC pauses.

Five alternating runs produced the following results:

Metric Current behavior Hardware cache
Retained hxcpp heap 311.5 MiB 55.2 MiB
Stable full-GC median 8–9 ms 8–9 ms
Stable full-GC p95 10.0–11.3 ms 10.0–11.6 ms

The optimization consistently saves about 256 MiB, matching the discarded pixel buffers. It does not produce a measurable reduction in full-GC pause times in this benchmark, since raw bitmap data contributes to the heap size but does not contain object references that the marker needs to traverse.

Real-world validation

These values should be considered indicative rather than a controlled benchmark.

Metric Current behavior Hardware cache Difference
Live heap 863.0 MiB 521.8 MiB -40%
Reserved heap 1100.2 MiB 741.3 MiB -33%
Large allocations 627.3 MiB 322.2 MiB -49%
Peak RSS 1903.8 MiB 1543.2 MiB -19%
Cumulative GC time 8231.4 ms 8223.4 ms effectively unchanged
Median GC pause 41.3 ms 39.7 ms similar
GC p95 137.4 ms 138.9 ms similar

This confirms a substantial reduction in retained memory without an observed GC regression. It does not demonstrate a direct improvement in GC pause times, so the primary purpose of this change is reducing memory retention and system memory pressure.

No visual regressions were observed with the final hardware/software cache classification.

Testing

The Animate tests run both with and without swf_hardware_bitmap_cache.

Validated with:

  • Haxe 4, feature disabled and enabled;
  • Haxe 3.4.7, feature disabled and enabled;
  • a native integration build using the hardware cache;
  • the included deterministic memory and GC repro.

Note: until 159db83 from #55 is merged, the Haxe 3 CI jobs may still fail earlier in AnimateTimeline.hx, independently of this PR.

@Tutez64

Tutez64 commented Jul 26, 2026

Copy link
Copy Markdown
Contributor Author

Follow-up: fixed a case where the same bitmap was referenced by both a hardware-compatible shape and a software/scale9 shape. Cache preparation now classifies all bitmap-fill references before instantiation, so shared assets remain CPU-readable regardless of creation order. Hardware-only assets are still disposed as before.
Regression coverage was added for the hardware-first instantiation order that previously caused a crash.

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