Commit History
-
preview: camera 12.5% further back (r 2 -> 2.25) so bulky models stay in frame for the whole turn
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>869d3b1
-
revert(app): extract_glb duration back to 60s
Test window is over - quota ran out before the 300s run happened, so the measurement is still outstanding. 300s must not sit in production: above 120s free tier users cannot run the Space at all. Everything else stays and is production-safe. Nothing added can end an extraction: the xatlas timeout is a 600s backstop well above the GPU duration, the mesh report is ~65ms, and the subprocess falls back to in-process if it cannot be used. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>d1779b3 -
test(xatlas): raise extract_glb to 300s and log real elapsed seconds
Owner asked to measure how long the dense tree actually needs ON the Space, rather than infer it from another machine. Two changes for that. extract_glb duration 60 -> 300. This crosses the 120s line in the warning above it, which matters: above 120s free tier users cannot run the Space. It is a temporary measurement, to be put back to 60. Replaced the faulthandler heartbeat with a plain thread that prints elapsed seconds. This works now and did not before: xatlas used to run in-process holding the GIL, so no Python thread could tick, which is why dump_traceback_later was used. Now that xatlas runs in a subprocess the parent blocks on I/O and releases the GIL, so a thread can report "still running, Ns elapsed" every 30s instead of dumping a full traceback. Either outcome is now a real number: it completes and logs its own time, or it is killed and the last tick shows how far it got. Note on why this cannot be judged from local runs: xatlas is CPU-only, it never touches CUDA. ZeroGP…0e39085 -
fix(xatlas): stop the 25s timeout preempting models that used to export
Regression I introduced. A 63289-face mesh that exported fine before now died at 25s, having never been given the 60s the Space is configured for. The timeout was cutting the GPU budget short. 25s was picked from how long a NORMAL mesh takes, which was the wrong reference. A dense mesh needing 40s is not pathological, just slow, and preempting it turns a working export into a failure. Anything below the @spaces.GPU duration silently shortens the budget. Timeout is now 600s: a backstop against a genuinely infinite hang and nothing else. The GPU duration is once again the only thing that decides how long xatlas may run, exactly as before any of this. Also removed the now-dead _decimate helper, and moved the heartbeat from 15s to 30s so a slow-but-working extraction stops spraying tracebacks through the log. What remains from this work is only additive: the mesh report, the subprocess isolation (with its in-process fallback), and the mesh dump on every run. None of them can end an ext…5191b26 -
revert(xatlas): drop the decimate-on-timeout fallback; dump the mesh every run
Reverting 8988c55. Two things were wrong with it. It keyed on a timeout, and a timeout only means slow - not pathological. Raising the step count or using denser settings would have pushed an otherwise fine model past 25s and silently cut it to a quarter of its faces. That is a trap in the normal pipeline, not a fix. And the output was not acceptable anyway: the reduced tree exported, but came out looking like papier-mache. Trading three quarters of the geometry for an export that completes is not a trade worth making. The deeper problem is that the root cause is still unknown. What was measured is that time scales with density - not why this mesh yields 11836 charts for 118830 faces where other models do not. Claiming a normal mesh produces "6-100" charts was unfounded: that came from synthetic spheres, not from any real generation out of this pipeline. So collect the missing evidence instead of guessing at it. The mesh handed to xatlas is now saved on EVERY extraction, not only o…cb541e0 -
fix(xatlas): reduce density on timeout - the only lever that actually works
With the failing mesh in hand (thanks to the download hook in d008192) this could finally be measured instead of guessed at. xatlas does not hang on it - it completes in 171s, which is simply past any usable ZeroGPU budget. Profiled offline on the real 59255v/118830f tree: faces time treatment result 118830 171.2s cap chart area still >171s 59414 49.5s weld+dedupe+tiny 223.1s (worse) 29706 6.5s spatial chunk 3^3 233.5s (worse) 14853 1.4s spatial chunk 4^3 211.7s (worse) max_cost=1.0 still >250s Time is super-quadratic in face count and every structural and option-level treatment failed. Chart count is not the driver either: a synthetic mesh with 11865 charts and 144000 faces packs in 1.7s, versus 11836 charts and 118830 faces here at 171s. The cost is in computing and parameterizing charts over geometry that is tangled at every scale, and density is the only thing that moves…8988c55 -
fix(xatlas): drop the disproven retry, hand back the mesh that hangs
The bounded retry from 833d1cf does not work. On the tree it timed out too, so whatever xatlas is stuck in is not something ChartOptions .max_chart_area controls, and my reading that the piecewise-recompute loop was the culprit is not supported. Removed rather than left in: it was spending 20s of a 60s budget to re-learn that every run. What the last run did establish: the subprocess isolation works. ZeroGPU was not disturbed, the timeout fired, and the failure surfaced as a real traceback instead of a silent worker death. That part stays. Since the mesh cannot be reproduced synthetically - it is one specific tree, ~5.1 area inside a unit box, denser than anything generated - stop guessing at the cause and recover the actual geometry: - XatlasTimeout carries the path to the exact verts/faces that hung. - extract_glb copies that into the Gradio session dir and returns it through the existing Download GLB button, so a failed extraction hands back a 2.1MB npz instead of a s…d008192 -
fix(xatlas): bound the unbounded piecewise-recompute loop that hangs on dense meshes
The logging shipped in 4ecb686 answered it: the tree does not crash, it hangs. Ten heartbeats at 15s intervals inside atlas.generate() and no "Fatal Python error", while the pre-flight report came back clean on every check - finite verts, indices in range, outlier_ratio 1.0x, zero duplicate faces, zero non-manifold edges. Nothing upstream is producing a bad mesh, and a 117k-face mesh of simple topology parametrizes in 14s. Cause, from the xatlas source: when LSCM returns a self-overlapping chart, runCreateAndParameterizeChartTask (XA_RECOMPUTE_CHARTS) retries it with a piecewise fallback that is an unbounded `for (;;)` loop. Each PiecewiseParam::computeChart() call clears four per-face/per-vertex bitsets across the whole chart and rescans for a seed from face 0, so if patches peel off small it degenerates to O(faces^2) with no iteration cap and no timeout. This tree is simply the first object dense enough to put a chart there - area 5.255 inside a 0.78x0.76x1.0 box, roughly 7x more co…833d1cf -
diag(xatlas): instrument parametrize_mesh to catch the silent GLB crash
The tree that dies on the final step leaves no traceback. xatlas runs in C++ on its own thread pool and holds the GIL for the whole call, so a Python watchdog thread cannot tick while it runs (measured: 1 tick where 38 were expected), and a native SIGSEGV kills the worker with an empty log. Raising the ZeroGPU duration to 300s changed nothing. Reproduced locally against the pinned xatlas 0.0.9: a clean 82k-face icosphere segfaults 10/10 runs, null deref in TaskScheduler::workerThread. Not driven by face count (a 180k-face single chart and a 128k-face sphere are both fine), not memory (peak RSS 0.21GB), and not fixed by 0.0.11. Unconfirmed on the Space's linux x86_64 wheel - that is what this is for. In parametrize_mesh only: - pre-flight mesh report: non-finite verts, index bounds, outlier ratio, degenerate/duplicate faces, components, boundary/non-manifold edges. Catches the two other xatlas pathologies found locally - one stray vertex produced a 1987263x11 atlas, near…4ecb686 -
revert: remove pymeshfix subprocess-timeout mechanism entirely - broke ZeroGPU
ZeroGPU runs @spaces.GPU-decorated functions inside a daemon process. Python's multiprocessing module hard-refuses to let a daemon process spawn children ("AssertionError: daemonic processes are not allowed to have children"), so any use of multiprocessing.Process from inside extract_glb was guaranteed to fail - independent of which module the worker lived in. This is why the previous fix attempt (moving the worker out of the trellis package) did not resolve it: that addressed a different, secondary problem, not the actual cause. This reverts to calling pymeshfix.fill_small_boundaries in-process exactly as before, with zero behavior change (verified via diff against d152cc4, the pre-instrumentation commit: postprocessing_utils.py now differs only by added print(..., flush=True) timing statements, app.py is byte-identical). The tree hang is still unsolved. Any future fix needs a mechanism that doesn't rely on multiprocessing.Process from within a ZeroGPU GPU task - e.g. subprocess.Pop…0238466 -
fix: move pymeshfix subprocess worker out of trellis package, revert GPU duration to 60
The previous commit's worker module lived under trellis/utils/, whose __init__.py eagerly imports models/modules/pipelines/renderers (torch, CUDA extensions, the whole pipeline). Spawning a subprocess that imports that module reimported the entire heavy stack - including touching CUDA - inside a spawned subprocess running alongside ZeroGPU's virtualized GPU context. This is the likely cause of "assertion failed" errors appearing on every object, not just the tree, after that push: the mere act of spawning the subprocess during Extract GLB corrupted the worker's GPU context, independent of any timeout. Move the worker to meshfix_hole_fill_worker.py at the app root (same pattern as utils_birefnet.py), which imports only numpy + pymeshfix and never touches torch/CUDA. Also make the worker subprocess persistent (spawned once, reused across calls) instead of spawned fresh per call, so normal exports pay a small IPC round-trip instead of a process-startup cost; it's only killed and respawne…d678c57 -
fix: hard-timeout pymeshfix hole-filling to stop indefinite hangs on high-branch-count meshes
Some assets (observed on a densely-branched tree) produce a mesh with an extreme number of tiny boundary loops after mincut. pymeshfix's C++ fill_small_boundaries has no in-process cancellation and was observed to hang indefinitely on the second pass (confirmed via its own "% done" progress output stalling at 0%, followed by ZeroGPU aborting the worker even with a 300s budget) - not just running slowly. Run both fill_small_boundaries passes in a spawned subprocess with a hard 20s timeout each; on timeout, kill the subprocess and continue with the pre-pass mesh instead of losing the whole export. Also add always-on (not gated by verbose=False) phase-timing prints through postprocess_mesh, _fill_holes, parametrize_mesh, and bake_texture so a future hang shows exactly which stage was in flight when the GPU worker gets aborted, since "done" prints never fire for a stage that never returns. Bump extract_glb's ZeroGPU duration 60->100 (within the existing 120s ceiling) to give headroom for…bba2503
-
fix: restore flash-attn 2.8.3 — hard import in trellis attention module
d152cc4 -
fix: remove flash-attn — caused RunPod xformers conflict, not required by either env
8b88814
-
docs: add inline documentation to all modified files
Detailed comments in app.py, gaussian_render.py, and requirements.txt explaining ZeroGPU environment constraints, why cu128 wheels are used, API differences from the TRELLIS fork, and what to update if ZeroGPU changes its torch/CUDA versions.cd2bf91 -
fix: use cu128 wheels matching ZeroGPU's torch CUDA 12.8 environment
ZeroGPU environment confirmed: torch.version.cuda='12.8', system CUDA 13.0. - Replaced cu126 wheels with cu128 builds from MiroPsota - Reverted to wheel-based install (source build blocked by CUDA version check) - Renderer API matches MiroPsota wheel: antialiasing=False, 3-value return966534b -
fix: build diff_gaussian_rasterization from source for H200 (sm_90) GPUs
Root cause: pre-built wheels were compiled for wrong GPU compute capability. ZeroGPU uses H200 Hopper GPUs (sm_90). Fix: - Build diff_gaussian_rasterization from official graphdeco-inria source at runtime with TORCH_CUDA_ARCH_LIST=9.0 - Remove incompatible pre-built wheel - Revert renderer to match official source API (no antialiasing param, 2-value return) - Add ninja for faster CUDA compilation - Keep nvdiffrast pre-built wheel (less arch-sensitive)84714e2 -
fix: disable NVML checks for ZeroGPU virtualized GPU environment
Set PYTORCH_NVML_BASED_CUDA_CHECK=0 before any imports to prevent NVML assertion failures in ZeroGPU's proxied GPU environment. Also enable expandable_segments for CUDA memory allocator.6b070eb -
fix: add antialiasing param and handle 3-value return from rasterizer
Verified the exact API of the installed diff_gaussian_rasterization wheel: - GaussianRasterizationSettings requires 'antialiasing' field (set False) - Rasterizer returns (color, radii, invdepths) not (color, radii) - All other deps (nvdiffrast, flash_attn, spconv) use stable APIs, no changes needed24dfefa -
fix: adapt gaussian renderer to standard diff_gaussian_rasterization API
Remove kernel_size (was 0.1, negligible anti-alias) and subpixel_offset (was all zeros) params that only exist in the custom TRELLIS fork. Standard version needed for torch 2.8 ABI compatibility.fb67d8b -
fix: replace wheels with torch 2.8.0 ABI-compatible builds
- nvdiffrast & diff_gaussian_rasterization wheels rebuilt for torch 2.8.0+cu126 (from MiroPsota/torch_packages_builder) - CUDA index switched from cu124 to cu126 - app.py: force-reinstall local wheels to override build-time installs - Removed upstream TRELLIS wheel URLs from requirements.txt (local wheels handle it)37bc42d -
fix: xformers 0.0.32 → 0.0.32.post2 (base version doesn't exist on PyPI)
699ccee -
fix: upgrade torch 2.4→2.8.0 for ZeroGPU compatibility
- torch 2.4.0 → 2.8.0 (minimum ZeroGPU-supported version) - torchvision 0.19.0 → 0.23.0 - xformers 0.0.27.post2 → 0.0.32 - flash_attn 2.7.0 → 2.8.3 (torch2.8 wheel) - CUDA index cu121 → cu124 - Added diff_gaussian_rasterization and nvdiffrast wheels5f1e6e0
-
Update app.py
Verified signature76d7b4b
-
Update app.py
Verified signaturec5d3e40
-
Pin fastapi and starlette to fix Gradio 4 compatibility
d656e74 -
Update GPU duration from 120s to 60s
dc50138
-
fix: handle non-RGB images in BiRefNet (CMYK, grayscale, LA modes)
Always convert to RGB before the transform pipeline to prevent shape mismatch errors with non-standard image modes.85ba34f
-
fix: remove gr.api() calls incompatible with installed Gradio version
5722c34 -
fix: add preprocessed_images to preprocess_multi; auto-detect multiimage mode from data in image_to_3d
dc11418
-
Bump max_hole_size to 0.06 - middle ground between 0.04 (too weak) and 0.1 (too aggressive)
63312ed -
Dial back hole-filling: revert max_hole_size to 0.04, modest nbe increase with floor of 96, keep simplify connection
033735d -
Improve hole-filling: higher thresholds, min nbe floor of 128, double-pass fill
db72024
-
Add warning comments for ZeroGPU limits
c27fcec -
Update GPU durations to 120s for ZeroGPU free tier
56ec3d2 -
Revert GPU durations to 180s to conform to ZeroGPU bounds
843aa16 -
Update generation and export duration to 240s
115e521
-
Fix CUDA runtime error on Stateless GPU ZeroGPU environment
54852a9
-
fix: add kornia+timm deps, use utils_birefnet.py wrapper (same as ASM-o2.1-MULTIIMAGE)
a031616 -
feat: use BiRefNet for background removal in both single and multi-image paths
98670cc -
fix: patch _json_schema_to_python_type to handle True/False bool schemas
99dc45e
-
fix: full Gradio 5.x compatibility - replace deprecated gr.update() with component returns
110972c -
fix: monkey-patch gradio_client bool schema bug directly at runtime
599c52b -
fix: pin gradio==4.44.1 for ssr_mode support, remove runpod dep
995c36b
-
Fix iPhone image orientation bug by adding pillow_heif
b2e81f0
-
fix: restore ssr_mode=False to prevent Gradio api_info() crash on startup
ef97a0b
-
fix: resolve build conflict + 150s export timeout
fa14cfd
-
Update gamma correction to 1.8
3b3032f -
Fix float type error in sampler steps
23f214e
-
Revert "Fix: Bypass C0 multiplication for DC-only SH - directly add 0.5 bias for correct shadow rendering"
This reverts commit 4d552879e0847f94a9a0674c55a44338fe189ac2.a4a2c5f