diff --git a/docs/fleettools/blender.md b/docs/fleettools/blender.md index fdb1956..1a0f453 100644 --- a/docs/fleettools/blender.md +++ b/docs/fleettools/blender.md @@ -24,10 +24,11 @@ scripts/blender-run -- --python-expr 'import bpy; print(bpy.app.version_string)' ``` - Always adds `-b --factory-startup --python-exit-code 1`. Arguments go after `--`. -- **Files:** fv-ml1 does not mount `/mnt/smithy`. `--job DIR` copies DIR to - `fv-ml1:/tank/blender/jobs//`, runs with that as the working directory, and copies - new or changed files back into DIR. Nothing is deleted on either side. Use relative - input paths inside the job. +- **Files:** fv-ml1 does not mount `/mnt/smithy`. `--job DIR` mirrors DIR to + `fv-ml1:/tank/blender/jobs/-/`, runs with that as + the working directory, and copies new or changed files back into DIR. Nothing is ever + deleted locally, and a rerun starts from an exact mirror, never from leftovers. Use + relative input paths inside the job. Do not run the same DIR twice at once. - **Engines headless (tested 2026-09-28):** Cycles on GPU (OptiX/CUDA), Cycles on CPU, EEVEE (EGL, no display needed, ~9 s with the shader compile on first use), Workbench. In 5.2 the EEVEE id is `BLENDER_EEVEE` (`BLENDER_EEVEE_NEXT` is gone). For Cycles GPU, set @@ -44,7 +45,9 @@ scripts/blender-run -- --python-expr 'import bpy; print(bpy.app.version_string)' sets it. - `render.filepath` must be **absolute**. Blender does not resolve a relative output path against the working directory ("cannot save 'out.png'"). Importers and Python file I/O do. -- "HIPEW initialization failed" on stderr is harmless: it is the AMD backend probing. +- Harmless stderr noise: "HIPEW initialization failed" (the AMD backend probing), and "Failed to + create secure directory (/defaults): Operation not permitted" (the image's runtime-dir setup + running as a non-root user; reported by draupnir 2026-09-28). - The first OptiX render in a process includes about 1-2 s of kernel load. ## blender-mcp (agents) diff --git a/scripts/blender-run b/scripts/blender-run index 7759f50..30846e9 100755 --- a/scripts/blender-run +++ b/scripts/blender-run @@ -16,10 +16,12 @@ # output path against the working directory: "cannot save 'out.png'". Python file I/O and # importers do use the cwd. # -# Files: fv-ml1 does NOT mount /mnt/smithy. With --job DIR, DIR is copied to -# fv-ml1:/tank/blender/jobs//, Blender runs WITH THAT AS ITS WORKING DIRECTORY, and new or -# changed files are copied back into DIR afterwards (nothing is deleted on either side). Use -# relative paths inside the job. Without --job, the only paths Blender sees are under +# Files: fv-ml1 does NOT mount /mnt/smithy. With --job DIR, DIR is mirrored to +# fv-ml1:/tank/blender/jobs/-/, Blender runs WITH THAT AS ITS +# WORKING DIRECTORY, and new or changed files are copied back into DIR afterwards (nothing is ever +# deleted locally). Use relative paths inside the job. Running the SAME DIR twice concurrently +# still shares one remote dir, so don't do that. Remote job dirs are never swept: one copy is kept +# per distinct DIR (small files, on /tank). Without --job, the only paths Blender sees are under # /work (= fv-ml1:/tank/blender). # # Budget: GPU 3 (96 GB, borrowed from the vLLM reserve: this ends if a full-size seat moves in). @@ -42,10 +44,16 @@ done WORKDIR=/work if [ -n "$JOB" ]; then [ -d "$JOB" ] || { echo "blender-run: --job $JOB is not a directory" >&2; exit 2; } - NAME=$(basename "$(realpath "$JOB")") - [[ $NAME =~ ^[A-Za-z0-9._-]+$ ]] || { echo "blender-run: job dir name '$NAME' must be [A-Za-z0-9._-]" >&2; exit 2; } + ABS=$(realpath "$JOB") + BASE=$(basename "$ABS") + [[ $BASE =~ ^[A-Za-z0-9._-]+$ ]] || { echo "blender-run: job dir name '$BASE' must be [A-Za-z0-9._-]" >&2; exit 2; } + # Keyed on basename + a hash of the ABSOLUTE local path (draupnir, 2026-09-28): two different + # dirs that share a basename no longer share a remote dir. `--delete` makes the remote an exact + # mirror of DIR, so a rerun never inherits an earlier run's leftovers. rsync removes only + # inside that one remote dir; there is no rm on a computed path. + NAME=$BASE-$(printf '%s' "$ABS" | sha256sum | cut -c1-8) ssh -n -o BatchMode=yes "$HOST" "mkdir -p /tank/blender/jobs/$NAME" - rsync -a "$JOB"/ "$HOST:/tank/blender/jobs/$NAME/" + rsync -a --delete "$JOB"/ "$HOST:/tank/blender/jobs/$NAME/" WORKDIR=/work/jobs/$NAME fi