Skip to content

feat: add GLB loading, single-frame output, and GPU recovery - #46

Open
marksverdhei wants to merge 2 commits into
mainfrom
feat/glb-frame-gpu-recovery
Open

feat: add GLB loading, single-frame output, and GPU recovery#46
marksverdhei wants to merge 2 commits into
mainfrom
feat/glb-frame-gpu-recovery

Conversation

@marksverdhei

@marksverdhei marksverdhei commented Sep 12, 2026

Copy link
Copy Markdown
Contributor

What & why

Adds GLB geometry loading, terminal-independent single-frame text output, and recoverable GPU errors. Models can be rendered into scripts with a3d model.glb --frame 12x10 --time 4.5. During interactive rendering, automatic mode switches to CPU after GPU setup, allocation, resize, or readback failure; forced GPU mode reports the error after restoring the terminal.

GLB and text export implement parts of roadmap #1; GPU device-loss handling addresses a deferred item in #3.

Behavior and scope

  • GLB: loads triangle primitives in the selected scene, applies node transforms and reflection winding, and combines material/vertex colors. Valid sparse accessors are supported. Accessor types, counts, strides, checked byte ranges, and sparse indices are validated before decoding; malformed inputs return errors. A 256 MiB per-accessor decoded budget bounds sparse expansion.
  • CLI: --frame WIDTHxHEIGHT writes a plain-text CPU frame without terminal/GPU initialization. Dimensions are 1–256; --time must be finite and non-negative. --frame --gpu is rejected.
  • GPU API: RasterPipeline::new, resize, and render_frame_gpu return Result. Callers must handle failures and use GpuContext::new() because device-loss tracking is private. GPU render errors clear the framebuffer; allocation/device errors require rebuilding the pipeline.
  • Output contract: documents floating-point parity tolerances and that GPU depth is not read back. Existing CPU snapshots are unchanged.

GLB support does not apply textures, animation, skinning, or morph targets; non-triangle topologies and external buffers are rejected. The accessor budget is not a total scene-memory limit. GPU scope overhead has not been benchmarked separately. These boundaries and API migration guidance are documented in README/SECURITY.

Validation

GitHub CI passes on cee7f77: Test and MSRV (Rust 1.85).

  • cargo fmt --all -- --check
  • cargo clippy --all-targets --all-features -- -D warnings
  • cargo test --all-features -- --test-threads=1 --nocapture: 70 passed, 1 intentionally ignored snapshot generator; GPU tests executed without adapter skips
  • RUSTDOCFLAGS="-D warnings" cargo doc --no-deps --all-features
  • cargo test --release --lib model::loader -- --test-threads=1: all 14 loader tests passed
  • git diff --check
  • Behavior tests: malformed GLB accessor counts/types/strides/offsets, sparse bounds/order/values, valid sparse geometry, frame/GPU argument conflict, device loss, resizing, and CPU/GPU parity
  • Existing CPU snapshots pass; regeneration unnecessary

The three malformed-accessor panics found during initial review are covered by passing regression tests. Generated/local files already match .gitignore; no additional ignore entries are needed.

@marksverdhei
marksverdhei marked this pull request as ready for review September 12, 2026 12:19
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