You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(renderer): SDF disk cache (closes#22) + npm packaging (#50)
* feat(renderer): on-disk cache for per-mesh SDFs (closes#22)
Cold launches re-baked every per-mesh 32³ R32Float SDF from scratch
even though the same content always produces the same voxel data.
Sponza's first 9 frames spent ~8 bakes/frame on this path; second
launch spent another 9.
This change content-hashes (positions + indices) at GPU upload time,
checks a platform-appropriate cache directory, and `queue.write_texture`s
the cached voxel bytes directly when the file exists — bypassing the
GPU dispatch entirely. Misses fall through to the existing bake; the
renderer encodes a copy_texture_to_buffer alongside each dispatch
and persists the readback to disk after the frame's main submit.
The next launch hits and skips the bake.
The cache is best-effort throughout: a corrupt entry, missing dir,
or write failure silently re-bakes. wasm32 has no filesystem path so
load returns None and store is gated out — web builds bake every
launch as before.
Cache layout:
- macOS / iOS / tvOS / watchOS: ~/Library/Caches/bloom/sdf
- Linux / Android: $XDG_CACHE_HOME/bloom/sdf
- Windows: %LOCALAPPDATA%\bloom\cache\sdf
- 16 B header (magic + version + voxel_res) + 128 KB R32Float payload
Sponza disk footprint: 68 × 128 KB = 8.7 MB (matches the issue's
budget). Disk reads happen synchronously at upload — a 128 KB read
from local cache is sub-millisecond.
The synchronous device.poll(Wait) on flush blocks for the bake
submission to finish before persisting; this is a cold-launch-only
stall (~9 frames) and the bake itself is the bottleneck on those
frames anyway. Async pipelining is a follow-up if the cold-launch
stall ever shows up in profiles.
8 new unit tests cover hash stability, change-detection on positions
and indices, count-vs-value distinguishability, store/load round-trip,
miss handling, size validation, and bad-magic rejection. cargo test
74/0 (was 66/0) on macOS, wasm32 cargo check clean.
* chore(pkg): prep @bloomengine/engine for npm publish
Rename from bloom to @bloomengine/engine (Perry FFI module ref
updated to match) and add a files: allowlist so the tarball ships
just TS sources, Rust crates, shaders/assets, the bloom_jolt shim,
and JoltPhysics/Jolt — vendored at publish time rather than fetched
at install so installs stay self-contained and reproducible.
.npmignore is belt-and-suspenders against target/, pkg/, build/,
and the multi-MB Jolt extras (Samples/Docs/UnitTests/Assets/…).
scripts/prepack.sh refuses to publish if the Jolt submodule isn't
initialised — deliberately not auto-initing so we don't silently
publish stale refs. Root MIT LICENSE added so the legal terms
travel with the package.
* chore(pkg): fix GitHub URLs to match actual Bloom-Engine/engine remote
* docs(pkg): npm install instructions and @bloomengine/engine imports
Now that the package is published to npm, swap every documented
import from "bloom" to "@bloomengine/engine" so the snippets actually
resolve against an installed package. README also gains an Install
section up front pointing at npm (plus bun/pnpm/yarn equivalents) and
the toolchain prereqs (Perry + Rust, wasm-pack for web).
* ci(release): publish @bloomengine/engine to npm on tag release
Adds a publish-npm job to the existing tag-driven release workflow.
Runs after github-release so a failed publish doesn't leave a
release-but-no-package state, and after the await-tests gate so we
never ship a tag that didn't pass CI.
Idempotent: re-checks npm before publishing and skips cleanly if the
version already exists (so workflow_dispatch on an old tag won't
double-publish). Checks out submodules recursively because the
prepack hook refuses to ship without JoltPhysics sources on disk,
and uses --provenance for the npm attestation badge.
Requires an NPM_TOKEN repo secret with publish rights on the
@bloomengine scope.
* ci(release): drop NPM_TOKEN, use npm trusted publishing via OIDC
The package is now configured on npmjs.com with this workflow as a
trusted publisher, so `id-token: write` is sufficient — npm publish
exchanges the GitHub OIDC token for a short-lived credential. No
long-lived NPM_TOKEN secret to rotate or leak, and provenance
attestation is automatic.
Copy file name to clipboardExpand all lines: README.md
+33-11Lines changed: 33 additions & 11 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -5,11 +5,33 @@
5
5
Write TypeScript. Ship native games — and now the web too.
6
6
Bloom compiles your game to Metal, DirectX 12, Vulkan, OpenGL, and WebGPU — one codebase for every platform.
7
7
8
+
## Install
9
+
10
+
```bash
11
+
npm install @bloomengine/engine
12
+
```
13
+
14
+
Or with your preferred package manager:
15
+
16
+
```bash
17
+
bun add @bloomengine/engine
18
+
pnpm add @bloomengine/engine
19
+
yarn add @bloomengine/engine
20
+
```
21
+
22
+
The npm package ships the TypeScript API alongside the engine's Rust sources and the bundled [JoltPhysics](https://github.com/jrouwe/JoltPhysics) C++ shim, so a single `install` is enough — there's no separate native download step.
23
+
24
+
You'll also need:
25
+
26
+
-**Perry** — the TypeScript AOT compiler that turns your game into a native binary or WASM module. It also drives the engine's native build.
27
+
-**Rust toolchain** ([rustup.rs](https://rustup.rs)) — Perry invokes Cargo to compile the engine's platform crate the first time you build for each target.
28
+
- For web builds only: [wasm-pack](https://rustwasm.github.io/wasm-pack/installer/) (`cargo install wasm-pack`).
0 commit comments