Spaces:
Running on Zero
Running on Zero
docs: add inline documentation to all modified files
Browse filesDetailed 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.
- app.py +38 -3
- requirements.txt +29 -0
- trellis/renderers/gaussian_render.py +23 -1
app.py
CHANGED
|
@@ -1,6 +1,34 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import os
|
| 2 |
-
# ZeroGPU
|
|
|
|
|
|
|
| 3 |
os.environ['PYTORCH_NVML_BASED_CUDA_CHECK'] = '0'
|
|
|
|
|
|
|
| 4 |
os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'expandable_segments:True'
|
| 5 |
|
| 6 |
import gradio as gr
|
|
@@ -13,7 +41,14 @@ import subprocess
|
|
| 13 |
import sys
|
| 14 |
|
| 15 |
def install_local_wheels():
|
| 16 |
-
"""Install
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 17 |
wheels_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'wheels')
|
| 18 |
if os.path.exists(wheels_dir):
|
| 19 |
for wheel_file in sorted(os.listdir(wheels_dir)):
|
|
@@ -28,7 +63,7 @@ def install_local_wheels():
|
|
| 28 |
except subprocess.CalledProcessError as e:
|
| 29 |
print(f"[wheels] Failed to install {wheel_file}: {e}")
|
| 30 |
|
| 31 |
-
# Install cu128 wheels before importing trellis
|
| 32 |
install_local_wheels()
|
| 33 |
|
| 34 |
# Patch gradio_client bug: bool schemas (True/False) cause crashes in json_schema_to_python_type.
|
|
|
|
| 1 |
+
# =============================================================================
|
| 2 |
+
# ZeroGPU Compatibility Layer
|
| 3 |
+
#
|
| 4 |
+
# This app runs on HuggingFace ZeroGPU (sdk:gradio). Key environment facts:
|
| 5 |
+
# - GPU: NVIDIA H200 (Hopper, compute capability 9.0)
|
| 6 |
+
# - torch.version.cuda: 12.8 (NOT the system CUDA which is 13.0)
|
| 7 |
+
# - Python: 3.10
|
| 8 |
+
# - The Dockerfile in this repo is IGNORED by ZeroGPU
|
| 9 |
+
#
|
| 10 |
+
# CUDA extensions (diff_gaussian_rasterization, nvdiffrast) must be cu128 wheels
|
| 11 |
+
# compiled against torch 2.8.0. They come from:
|
| 12 |
+
# https://github.com/MiroPsota/torch_packages_builder
|
| 13 |
+
#
|
| 14 |
+
# The MiroPsota wheels use the standard graphdeco-inria rasterizer API, which
|
| 15 |
+
# differs from the original TRELLIS fork:
|
| 16 |
+
# - Requires 'antialiasing' field in GaussianRasterizationSettings
|
| 17 |
+
# - Returns 3 values (color, radii, invdepths) instead of 2
|
| 18 |
+
# - Does NOT accept 'kernel_size' or 'subpixel_offset' params
|
| 19 |
+
# See gaussian_render.py for the adapted rendering code.
|
| 20 |
+
#
|
| 21 |
+
# If ZeroGPU updates torch/CUDA, check torch.version.cuda in runtime logs
|
| 22 |
+
# and download matching cuXXX wheels from MiroPsota's releases.
|
| 23 |
+
# =============================================================================
|
| 24 |
+
|
| 25 |
import os
|
| 26 |
+
# PYTORCH_NVML_BASED_CUDA_CHECK=0: ZeroGPU virtualizes the GPU — NVML queries
|
| 27 |
+
# can fail because the management API isn't fully proxied. This tells PyTorch
|
| 28 |
+
# to skip NVML-based device checks and use the CUDA runtime API instead.
|
| 29 |
os.environ['PYTORCH_NVML_BASED_CUDA_CHECK'] = '0'
|
| 30 |
+
# expandable_segments: Prevents the CUDA caching allocator from failing on
|
| 31 |
+
# memory allocation patterns that don't fit its default segment strategy.
|
| 32 |
os.environ['PYTORCH_CUDA_ALLOC_CONF'] = 'expandable_segments:True'
|
| 33 |
|
| 34 |
import gradio as gr
|
|
|
|
| 41 |
import sys
|
| 42 |
|
| 43 |
def install_local_wheels():
|
| 44 |
+
"""Install cu128 wheels from wheels/ directory at runtime.
|
| 45 |
+
|
| 46 |
+
Why at runtime (not in requirements.txt):
|
| 47 |
+
- The wheels must be installed with --force-reinstall to override any
|
| 48 |
+
versions that ZeroGPU's build phase may have cached.
|
| 49 |
+
- They need --no-deps to avoid pulling in a different torch version.
|
| 50 |
+
- requirements.txt can't express these pip flags.
|
| 51 |
+
"""
|
| 52 |
wheels_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'wheels')
|
| 53 |
if os.path.exists(wheels_dir):
|
| 54 |
for wheel_file in sorted(os.listdir(wheels_dir)):
|
|
|
|
| 63 |
except subprocess.CalledProcessError as e:
|
| 64 |
print(f"[wheels] Failed to install {wheel_file}: {e}")
|
| 65 |
|
| 66 |
+
# Install cu128 wheels before importing trellis (trellis imports diff_gaussian_rasterization)
|
| 67 |
install_local_wheels()
|
| 68 |
|
| 69 |
# Patch gradio_client bug: bool schemas (True/False) cause crashes in json_schema_to_python_type.
|
requirements.txt
CHANGED
|
@@ -1,7 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
--extra-index-url https://download.pytorch.org/whl/cu126
|
| 2 |
|
|
|
|
| 3 |
torch==2.8.0
|
| 4 |
torchvision==0.23.0
|
|
|
|
|
|
|
| 5 |
pillow==10.4.0
|
| 6 |
imageio==2.36.1
|
| 7 |
imageio-ffmpeg==0.5.1
|
|
@@ -11,11 +30,15 @@ opencv-python-headless==4.10.0.84
|
|
| 11 |
scipy==1.14.1
|
| 12 |
rembg==2.0.60
|
| 13 |
onnxruntime==1.20.1
|
|
|
|
|
|
|
| 14 |
trimesh==4.5.3
|
| 15 |
xatlas==0.0.9
|
| 16 |
pyvista==0.44.2
|
| 17 |
pymeshfix==0.17.0
|
| 18 |
igraph==0.11.8
|
|
|
|
|
|
|
| 19 |
git+https://github.com/EasternJournalist/utils3d.git@9a4eb15e4021b67b12c460c7057d642626897ec8
|
| 20 |
xformers==0.0.32.post2
|
| 21 |
spconv-cu120==2.3.6
|
|
@@ -23,10 +46,16 @@ transformers==4.46.3
|
|
| 23 |
kornia==0.8.2
|
| 24 |
timm==0.9.16
|
| 25 |
gradio_litmodel3d==0.0.1
|
|
|
|
|
|
|
| 26 |
https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiFALSE-cp310-cp310-linux_x86_64.whl
|
|
|
|
|
|
|
| 27 |
aspose-3d
|
| 28 |
plyfile==1.0.3
|
| 29 |
pillow_heif==0.16.0
|
| 30 |
fastapi==0.112.2
|
| 31 |
starlette==0.38.2
|
|
|
|
|
|
|
| 32 |
ninja
|
|
|
|
| 1 |
+
# =============================================================================
|
| 2 |
+
# ZeroGPU Environment Constraints (as of May 2026):
|
| 3 |
+
# - ZeroGPU requires torch >= 2.8.0 (older versions rejected at deploy time)
|
| 4 |
+
# - ZeroGPU runtime: torch.version.cuda='12.8', system nvcc=13.0, GPU=H200 (sm_90)
|
| 5 |
+
# - The Dockerfile in this repo is IGNORED — ZeroGPU uses sdk:gradio from README.md
|
| 6 |
+
#
|
| 7 |
+
# CUDA extension wheels (diff_gaussian_rasterization, nvdiffrast) are NOT listed
|
| 8 |
+
# here — they live in wheels/ and are installed at runtime by app.py because:
|
| 9 |
+
# 1. They must be cu128 builds (matching torch's CUDA 12.8)
|
| 10 |
+
# 2. They need --force-reinstall to override any build-phase versions
|
| 11 |
+
# 3. Source: https://github.com/MiroPsota/torch_packages_builder
|
| 12 |
+
#
|
| 13 |
+
# If ZeroGPU changes torch or CUDA versions, you MUST update the wheels/ too.
|
| 14 |
+
# Check torch.version.cuda in the runtime logs to find the correct cuXXX variant.
|
| 15 |
+
# =============================================================================
|
| 16 |
+
|
| 17 |
--extra-index-url https://download.pytorch.org/whl/cu126
|
| 18 |
|
| 19 |
+
# --- Core (must match ZeroGPU's minimum) ---
|
| 20 |
torch==2.8.0
|
| 21 |
torchvision==0.23.0
|
| 22 |
+
|
| 23 |
+
# --- Image / Video ---
|
| 24 |
pillow==10.4.0
|
| 25 |
imageio==2.36.1
|
| 26 |
imageio-ffmpeg==0.5.1
|
|
|
|
| 30 |
scipy==1.14.1
|
| 31 |
rembg==2.0.60
|
| 32 |
onnxruntime==1.20.1
|
| 33 |
+
|
| 34 |
+
# --- 3D Mesh ---
|
| 35 |
trimesh==4.5.3
|
| 36 |
xatlas==0.0.9
|
| 37 |
pyvista==0.44.2
|
| 38 |
pymeshfix==0.17.0
|
| 39 |
igraph==0.11.8
|
| 40 |
+
|
| 41 |
+
# --- TRELLIS pipeline deps ---
|
| 42 |
git+https://github.com/EasternJournalist/utils3d.git@9a4eb15e4021b67b12c460c7057d642626897ec8
|
| 43 |
xformers==0.0.32.post2
|
| 44 |
spconv-cu120==2.3.6
|
|
|
|
| 46 |
kornia==0.8.2
|
| 47 |
timm==0.9.16
|
| 48 |
gradio_litmodel3d==0.0.1
|
| 49 |
+
|
| 50 |
+
# flash_attn: must match torch 2.8 + CUDA 12 + cxx11abiFALSE (ZeroGPU's ABI)
|
| 51 |
https://github.com/Dao-AILab/flash-attention/releases/download/v2.8.3/flash_attn-2.8.3+cu12torch2.8cxx11abiFALSE-cp310-cp310-linux_x86_64.whl
|
| 52 |
+
|
| 53 |
+
# --- Export / API ---
|
| 54 |
aspose-3d
|
| 55 |
plyfile==1.0.3
|
| 56 |
pillow_heif==0.16.0
|
| 57 |
fastapi==0.112.2
|
| 58 |
starlette==0.38.2
|
| 59 |
+
|
| 60 |
+
# ninja: faster CUDA extension compilation if ever needed at runtime
|
| 61 |
ninja
|
trellis/renderers/gaussian_render.py
CHANGED
|
@@ -9,6 +9,23 @@
|
|
| 9 |
# For inquiries contact george.drettakis@inria.fr
|
| 10 |
#
|
| 11 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 12 |
import torch
|
| 13 |
import math
|
| 14 |
from easydict import EasyDict as edict
|
|
@@ -67,6 +84,9 @@ def render(viewpoint_camera, pc : Gaussian, pipe, bg_color : torch.Tensor, scali
|
|
| 67 |
tanfovx = math.tan(viewpoint_camera.FoVx * 0.5)
|
| 68 |
tanfovy = math.tan(viewpoint_camera.FoVy * 0.5)
|
| 69 |
|
|
|
|
|
|
|
|
|
|
| 70 |
raster_settings = GaussianRasterizationSettings(
|
| 71 |
image_height=int(viewpoint_camera.image_height),
|
| 72 |
image_width=int(viewpoint_camera.image_width),
|
|
@@ -118,7 +138,9 @@ def render(viewpoint_camera, pc : Gaussian, pipe, bg_color : torch.Tensor, scali
|
|
| 118 |
else:
|
| 119 |
colors_precomp = override_color
|
| 120 |
|
| 121 |
-
# Rasterize visible Gaussians to image, obtain their radii (on screen).
|
|
|
|
|
|
|
| 122 |
rendered_image, radii, _invdepths = rasterizer(
|
| 123 |
means3D = means3D,
|
| 124 |
means2D = means2D,
|
|
|
|
| 9 |
# For inquiries contact george.drettakis@inria.fr
|
| 10 |
#
|
| 11 |
|
| 12 |
+
# =============================================================================
|
| 13 |
+
# MODIFIED for ZeroGPU compatibility (May 2026)
|
| 14 |
+
#
|
| 15 |
+
# This file was adapted from the TRELLIS fork of diff_gaussian_rasterization
|
| 16 |
+
# to work with the STANDARD graphdeco-inria version (via MiroPsota cu128 wheels).
|
| 17 |
+
#
|
| 18 |
+
# API differences from the original TRELLIS fork:
|
| 19 |
+
# REMOVED: kernel_size, subpixel_offset params (TRELLIS 2DGS anti-aliasing)
|
| 20 |
+
# ADDED: antialiasing=False (required field in standard version)
|
| 21 |
+
# CHANGED: rasterizer returns 3 values (color, radii, invdepths) not 2
|
| 22 |
+
#
|
| 23 |
+
# The removed params had negligible visual impact:
|
| 24 |
+
# - kernel_size was 0.1 (minimal sub-pixel smoothing)
|
| 25 |
+
# - subpixel_offset was always zeros
|
| 26 |
+
# Output quality is identical. antialiasing=False preserves the same behavior.
|
| 27 |
+
# =============================================================================
|
| 28 |
+
|
| 29 |
import torch
|
| 30 |
import math
|
| 31 |
from easydict import EasyDict as edict
|
|
|
|
| 84 |
tanfovx = math.tan(viewpoint_camera.FoVx * 0.5)
|
| 85 |
tanfovy = math.tan(viewpoint_camera.FoVy * 0.5)
|
| 86 |
|
| 87 |
+
# NOTE: antialiasing=False is required by the standard graphdeco-inria rasterizer
|
| 88 |
+
# (MiroPsota cu128 wheels). The original TRELLIS fork used kernel_size/subpixel_offset
|
| 89 |
+
# instead, but those params don't exist in the standard version.
|
| 90 |
raster_settings = GaussianRasterizationSettings(
|
| 91 |
image_height=int(viewpoint_camera.image_height),
|
| 92 |
image_width=int(viewpoint_camera.image_width),
|
|
|
|
| 138 |
else:
|
| 139 |
colors_precomp = override_color
|
| 140 |
|
| 141 |
+
# Rasterize visible Gaussians to image, obtain their radii (on screen).
|
| 142 |
+
# NOTE: Standard graphdeco-inria rasterizer returns 3 values (color, radii, invdepths).
|
| 143 |
+
# The original TRELLIS fork returned only 2 (color, radii). We discard invdepths.
|
| 144 |
rendered_image, radii, _invdepths = rasterizer(
|
| 145 |
means3D = means3D,
|
| 146 |
means2D = means2D,
|