Skip to main content

debug-operation

Triage a failing Usd Optimize operation. Use when an op errors, silently no-ops, or returns unexpected output.

Quellinformationen

Repository
NVIDIA-Omniverse/usd-optimize
Letzte Quellaktivität
1. Oktober 2026 um 01:28
Erkannte Sprache von SKILL.md
Englisch
Sterne
36
Forks
7

Installationsoptionen

Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.

Quelldateien prüfen

Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.

SKILL.md wird angezeigt

SKILL.md
Quellanweisungen · Schreibgeschützte Vorschau
name
debug-operation
description
Triage a failing Usd Optimize operation. Use when an op errors, silently no-ops, or returns unexpected output.
allowed-tools
Shell, Read, Grep, Glob
metadata
{"author":"NVIDIA Corporation","version":"1.0.1","tags":["debug","troubleshooting","operations"]}
<!-- SPDX-FileCopyrightText: Copyright (c) 2026 NVIDIA CORPORATION & AFFILIATES. All rights reserved. --> <!-- SPDX-License-Identifier: Apache-2.0 --> # Debug Operation Structured workflow for triaging an operation that fails, produces unexpected output, or silently does nothing. ## What this skill covers Search this doc for keywords like `verbose`, `analysisMode`, `argument key`, `silent no-op`, `mesh-less`, `instanced`, `libusd` to jump. - **Step 1** — reproduce and capture the log. - **Step 2** — check the basics (argument keys, input stage). - **Step 3** — enable verbose + analysis mode. - **Step 4** — diagnose by failure pattern (tables for common failure modes). - **Operation-family cheat sheet** — per-family gotchas. Companion skills: `run-operations` (how to invoke), `tune-parameters` (when the op runs but the output isn't right), `build` (when the build itself is broken). --- ## Step 1 — Reproduce and capture the log Run the operation through the `usdOptimize` CLI with full logging, and omit `-w` so no (bad) output file is written. ```bash # POSIX — verbose, capture stats, no output written BIN=_build/linux-x86_64/release/bin/usdOptimize "$BIN" -i "$ASSET" -o <key> -a <arg>=<val> -v -s > "$TMPDIR/debug-run.log" 2>&1 ``` `-v` is verbose and `-s` captures before/after stats. Omitting `-w` means nothing is written. The log captures the C++ `[INFO]`/`[WARN]`/`[ERROR]` lines. For a multi-op chain, use `-c <config.json>` instead of `-o`/`-a`. **Do not add `-r` here.** `-r` diverts the operation's warnings into the report file instead of stdout, so `[WARNING]` lines the checks below grep for never reach your log. If you also want the report, run a second pass with `-r` added rather than folding it into this one. If the user already has a log (e.g. from a prior `run-operations` run), skip this step and read their log directly. ## Step 2 — Check the basics Most "operation does nothing" reports fall into one of three categories. Check them in order before going deeper. ### 2a. Argument key mismatch An unknown key in a `-c` config logs `[WARNING] Unknown argument '<key>' for operation '<op>' -- ignoring it` and the operation runs with the default, so grep the log for `Unknown argument` first. (Via `-a` it's a hard error instead: `Error: invalid argument specified`, exit 1.) Verify every key in the user's config matches the operation's `addArgument()` declarations: ```bash # Check the C++ source for the canonical argument keys rg 'addArgument' source/operations/<key>/ --glob '*.cpp' --glob '*.h' ``` Or check the argument list in `docs/operations/<key>.rst`. Common mistakes: - Camel-case vs snake-case (`mergeVertices` not `merge_vertices`). - Plural vs singular (`paths` not `path`, `meshPrimPaths` not `meshPrimPath`). - Boolean as string (`true` not `"true"` in JSON). ### 2b. Wrong operation key The operation key is the first string argument to the `Operation(...)` base constructor, not the class name or the `USD_OPTIMIZE_PLUGIN_INIT` argument. Verify: ```bash rg 'Operation\(' source/operations/<key>/ --glob '*.cpp' -A1 | head -5 ``` ### 2c. Input stage has no matching prims Many operations scope work via a `paths` argument or operate only on specific prim types. If the stage has no prims matching the filter, the operation returns success but does nothing. ```python # Quick check: does the stage have meshes? from pxr import Usd, UsdGeom stage = Usd.Stage.Open("<asset>") meshes = [p for p in stage.TraverseAll() if p.IsA(UsdGeom.Mesh)] print(f"{len(meshes)} meshes") ``` ## Step 3 — Enable verbose and analysis mode If the basics check out, run in analysis mode to see what the operation *would* do without mutating the stage: ```python from usd_optimize.core import ExecutionContext, UsdOptimizeCore from pxr import Usd, UsdUtils stage = Usd.Stage.Open("<asset>") context = ExecutionContext() context.usdStageId = UsdUtils.StageCache.Get().Insert(stage).ToLongInt() context.analysisMode = 1 context.verbose = 1 success, error, output = UsdOptimizeCore.getInstance().executeOperation( "<key>", context, {<args>} ) print("success:", success) print("error:", error) print("output:", output) ``` Not all operations support analysis mode. Check: ```bash rg 'getSupportsAnalysis' source/operations/<key>/ --glob '*.cpp' ``` If the operation doesn't override `getSupportsAnalysis`, analysis mode is unavailable — fall back to running on a disposable copy of the stage. For the full CLI flag reference (`-v`, `-s`, `-an`, `-r`, `-st`), see `docs/cli.rst`. ## Step 4 — Diagnose by failure pattern ### Hard failures (operation returns error) | Log pattern | Likely cause | Fix | |---|---|---| | `Stage not found` or `Invalid stage id` | `ExecutionContext.usdStageId` not set or stale. | Use `context.set_stage(stage)` or set `usdStageId` via `UsdUtils.StageCache`. | | `Operation '<key>' not found` | Operation plugin didn't load — either not built or not on the plugin search path. | Rebuild (`./repo.sh build`). Check `UsdOptimizeCore.getInstance().getOperations()` for the registered list. | | `libusd` mismatch / stage-cache miss (see `Operation.cpp` error) | Two copies of `libusd` loaded — Python's `pxr` resolves to a different one than the C++ core. | Use the build's bundled Python via the wrapper scripts. See `run-validators` § CLI invocation for the `libusd` alignment exports. | | Crash / segfault during execution | Usually a real bug. | Isolate the failing prim path, write a minimal repro, and file against the operation. | ### Silent no-ops (operation returns success, nothing changed) | Pattern | Likely cause | Fix | |---|---|---| | Operation produces **no log line at all** | `paths` matched nothing. No operation prints a "0 processed" line, so silence *is* the signal — and the exit code is still 0. | Check the `paths` argument (see the bare-path rule below). An empty `paths` array means "all prims" for most ops, but some interpret it as "nothing selected." | | `paths` set to a bare non-Mesh prim path | A bare path matches **only that one prim**. `paths=/World` on an Xform therefore matches nothing, silently, with exit 0 and no output. | Use the SdfPathExpression descendant form `/World//*`, or list both (`["/World", "/World//*"]`) when the target may itself be the Mesh. | | Operation ran but output is identical to input | Arguments are at defaults that produce no change (e.g. `reductionFactor: 100` keeps everything). | Review the parameter defaults in the guide or C++ source. | | Log shows processing but the save failed | No `-w`/`--write` output path was given, or `stage.GetRootLayer().Save()` / `.Export()` wasn't called. | Check the runner output for the save step. (There is no `--no-save` flag — omitting `-w` is how you run without writing.) | ### Unexpected output (operation ran but result is wrong) | Pattern | Likely cause | Fix | |---|---|---| | Only some prims were affected | Operation scoped by `paths` or a prim-type filter. | Widen `paths` or check `meshPrimPaths` / similar scope arguments. | | Values look wrong (e.g. extreme decimation) | World-unit mismatch — parameter values are in stage units, and `metersPerUnit` doesn't match assumptions. | Check `UsdGeom.GetStageMetersPerUnit(stage)` and scale parameters accordingly. | | Merge produced unexpected grouping | `mergePoint` / `rootPath` / `considerMaterials` settings. | See `docs/operations/merge.rst`. | --- ## Operation-family cheat sheet ### Mesh operations (`meshCleanup`, `decimateMeshes`, `merge`, etc.) - Require `UsdGeomMesh` prims. No meshes = no work. - `merge` won't merge a boundary with a single mesh unless `allowSingleMeshes: true`. - `decimateMeshes` can't reduce below the topological minimum per mesh. Assets with many small parts will overshoot the target percentage. - `reductionFactor` is a percentage (0–100), not a fraction. `0.5` means "keep 0.5%", not "keep 50%". ### Deduplication (`deduplicateGeometry`, `deduplicateHierarchies`) - Prims with existing references/payloads are excluded from grouping. - Instanced prims can't be authored in place — deinstance first. - `deduplicateHierarchies` traverses from the stage's default prim. No default prim = no work. - Material-related prims (`Material`, `Shader`, `NodeGraph`, `Looks`, `Materials` scopes) are intentionally skipped. ### Analysis-only operations (`findCoincidingGeometry`, `findFlatHierarchies`, `findOverlappingMeshes`, `findOccludedMeshes`) - These detect but don't fix. The "fix" is a separate operation (e.g. `removePrims`, `flattenHierarchy`). - Results come back in `output["analysis"]` — inspect that dict. ### Material operations (`optimizeMaterials`) - `optimizeMaterialsMode: 1` ("Convert to color") replaces material networks with flat colors. Unintended if the user didn't ask for it. The mode is an enum, not a boolean: `0` Deduplicate (the default), `1` Convert to color, `2` Remove unbound, `3` Deduplicate with primvars. ### Hierarchy operations (`flattenHierarchy`, `pruneLeaves`) - These operate on the prim hierarchy, so they run on mesh-less stages too. - `flattenHierarchy` has params that control depth; defaults may not flatten enough. --- ## See also - `docs/operations/<key>.rst` — per-operation parameter reference and tuning guidance. - `docs/cli.rst` — CLI flags (`-v`, `-s`, `-an`, `-r`, ...). - `.agents/skills/run-operations/SKILL.md` — errors table for driver failures. - `.agents/skills/tune-parameters/SKILL.md` — when the operation runs but output quality needs iteration. ## Purpose Provide a structured triage workflow for an Usd Optimize operation that fails, silently no-ops, or produces unexpected output. Unifies log reading, argument verification, verbose / analysis-mode invocation, and a per-family cheat-sheet of common failure patterns so the agent can move from a vague "it didn't work" report to a concrete root cause without guessing. ## Prerequisites - A built repo (`./repo.sh build` or `repo.bat build`) — verbose / analysis-mode invocation requires the bundled Python. - The operation key (e.g. `meshCleanup`) and the user's invocation — config JSON, command line, or Python snippet — so the actual arguments are known. - A reproducible invocation. If the failure is intermittent, capture a log first with `--verbose -s` and no `-w` (there is no `--no-save` or `--captureStats` flag; `-s`/`--stats` is the stats switch). ## Limitations - This skill does not patch C++ source — its output is a diagnosis, not a code fix. For changes to the operation itself, the user works in `source/operations/<key>/` directly. - Analysis mode is unavailable for operations that don't override `getSupportsAnalysis()`. The skill falls back to running on a disposable stage copy in those cases. - Crashes / segfaults are surfaced as bug reports — the skill won't attach a debugger or symbolicate stacks. ## Troubleshooting This whole skill *is* a troubleshooting guide for Usd Optimize operations. The table below covers the meta-failure modes — when this skill itself can't make progress. | Symptom | Likely cause | Fix | |---|---|---| | Verbose log is empty | `executionContext` step missing or placed after the failing op. | Put `{"operation":"executionContext","verbose":1}` as the first config entry. **Use `1`, not `true`** — the parser reads these keys with `IsInt()`, so a JSON boolean is silently ignored. `captureStats` is not a recognised key here; use the CLI `-s` instead. | | Analysis mode reports `not supported` | Operation doesn't implement `executeAnalysisImpl`. | Drop analysis mode; run on a copy of the stage and omit `-w` so nothing is written. | | Op succeeds standalone but fails in chain | Earlier step in the chain mutated the stage in a way that invalidates the inputs. | Bisect the chain — run the failing op directly after the input is loaded. | | `libusd` mismatch error from `Operation.cpp` | Two `libusd` builds loaded — typical with system `pxr` + dev-tree Usd Optimize. | Use the build's bundled Python via the wrapper scripts (`tools/perf_*/run.sh`). See `run-validators` § CLI invocation for the `libusd` alignment exports. |
Auf GitHub ansehen