Honor replicate_physics in replication sessions#6541
Conversation
Greptile SummaryThis PR restores the
Confidence Score: 5/5Safe to merge. The change is minimal and narrowly scoped: it adds a flag that defaults to the current behavior so no existing caller is affected, and the fix is well-covered by unit tests. The logic correctly uses getattr(BackendCtxCls, 'replicates_physics', False) before instantiation, so physics contexts are never constructed when the flag is off. The queue is always drained upfront, preventing stale entries from bleeding into the next session. All three physics backends are consistently marked, and the True default means existing callers need no changes. No files require special attention. Authors of future physics-backend replication contexts should remember to add replicates_physics = True, or their backend will be dispatched even when replicate_physics=False. Important Files Changed
Sequence Diagram%%{init: {'theme': 'neutral'}}%%
sequenceDiagram
participant IS as InteractiveScene
participant RS as ReplicateSession
participant Q as REPLICATION_QUEUE
participant R as replicate()
participant PB as PhysicsBackendCtx
participant UB as UsdBackendCtx
IS->>RS: __init__(replicate_physics)
IS->>RS: __enter__()
Note over RS: make_clone_plan()
Note over IS,Q: Asset constructors queue physics backends
IS->>Q: append((cfg, PhysxReplicateContext))
IS->>Q: append((cfg, NewtonReplicateContext))
IS->>RS: __exit__()
RS->>R: replicate(plan, stage, replicate_physics)
Note over R,Q: drain queue upfront
alt replicate_physics is True
R->>PB: PB(stage).queue_mapping() then .replicate()
R->>UB: UB(stage).queue_mapping() then .replicate()
else replicate_physics is False
Note over R,PB: replicates_physics=True contexts skipped
R->>UB: UB(stage).queue_mapping() then .replicate()
end
R->>IS: SimulationContext.set_clone_plan(plan)
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
sequenceDiagram
participant IS as InteractiveScene
participant RS as ReplicateSession
participant Q as REPLICATION_QUEUE
participant R as replicate()
participant PB as PhysicsBackendCtx
participant UB as UsdBackendCtx
IS->>RS: __init__(replicate_physics)
IS->>RS: __enter__()
Note over RS: make_clone_plan()
Note over IS,Q: Asset constructors queue physics backends
IS->>Q: append((cfg, PhysxReplicateContext))
IS->>Q: append((cfg, NewtonReplicateContext))
IS->>RS: __exit__()
RS->>R: replicate(plan, stage, replicate_physics)
Note over R,Q: drain queue upfront
alt replicate_physics is True
R->>PB: PB(stage).queue_mapping() then .replicate()
R->>UB: UB(stage).queue_mapping() then .replicate()
else replicate_physics is False
Note over R,PB: replicates_physics=True contexts skipped
R->>UB: UB(stage).queue_mapping() then .replicate()
end
R->>IS: SimulationContext.set_clone_plan(plan)
Reviews (1): Last reviewed commit: "fix: honor replicate_physics in replicat..." | Re-trigger Greptile |
|
Thanks again for identifying this regression and the repro, @nblauch! I've opened #6550 as an alternative mechanism for the same fix, following the design discussion on our side: assets register their replication contexts as a per-cfg list (capability as data), and the scene — the owner of the The |
Since the replication-session refactor, InteractiveSceneCfg.replicate_physics was ignored: scenes configured with replicate_physics=False invoked native physics replication anyway, silently discarding per-environment USD differences (identified in isaac-sim#6541). The flag now lives where the policy executes: - CloneCfg.replicate_physics is the policy's home; InteractiveScene pipes its cfg flag into it and forwards it through ReplicateSession to replicate(). - REPLICATION_QUEUE holds bare asset cfgs: construction only registers which cfgs participate (required by ClonePlan.from_env_0 in direct workflows and to distinguish clonable assets from lights/terrain). - replicate() resolves how each cfg clones at dispatch: the cfg's cloning_contexts field when set, otherwise the active backend's default stack exported as isaaclab_<backend>.cloner.REPLICATION. PhysX pairs physics replication with USD clones (collision groups are authored on the per-env prims; PhysX has no kitless mode), Newton includes USD only under Kit, and OvPhysX replicates alone since its clone replay authors USD. - With replicate_physics=False, cloning is USD-only: the physics engine parses the per-env USD prims directly; an asset whose contexts are all physics-based is simply not cloned. Asset implementations know nothing about cloning beyond registering their cfg; per-asset overrides are a cfg assignment. The per-backend queue_*_replication helpers are removed in favor of this single path.
Since the replication-session refactor, InteractiveSceneCfg.replicate_physics was ignored: scenes configured with replicate_physics=False invoked native physics replication anyway, silently discarding per-environment USD differences (identified in isaac-sim#6541). The flag now lives where the policy executes: - CloneCfg.replicate_physics is the policy's home; InteractiveScene pipes its cfg flag into it and forwards it through ReplicateSession to replicate(). - REPLICATION_QUEUE holds bare asset cfgs: construction only registers which cfgs participate (required by ClonePlan.from_env_0 in direct workflows and to distinguish clonable assets from lights/terrain). - replicate() resolves how each cfg clones at dispatch: the cfg's cloning_contexts field when set, otherwise the active backend's default stack exported as isaaclab_<backend>.cloner.REPLICATION. PhysX pairs physics replication with USD clones (collision groups are authored on the per-env prims; PhysX has no kitless mode), Newton includes USD only under Kit, and OvPhysX replicates alone since its clone replay authors USD. - With replicate_physics=False, cloning is USD-only: the physics engine parses the per-env USD prims directly; an asset whose contexts are all physics-based is simply not cloned. Asset implementations know nothing about cloning beyond registering their cfg; per-asset overrides are a cfg assignment. The per-backend queue_*_replication helpers are removed in favor of this single path.
Since the replication-session refactor, InteractiveSceneCfg.replicate_physics was ignored: scenes configured with replicate_physics=False invoked native physics replication anyway, silently discarding per-environment USD differences (identified in isaac-sim#6541). The flag now lives where the policy executes: - CloneCfg.replicate_physics is the policy's home; InteractiveScene pipes its cfg flag into it and forwards it through ReplicateSession to replicate(). - REPLICATION_QUEUE holds bare asset cfgs: construction only registers which cfgs participate (required by ClonePlan.from_env_0 in direct workflows and to distinguish clonable assets from lights/terrain). - replicate() resolves how each cfg clones at dispatch: the cfg's cloning_contexts field when set, otherwise the active backend's default stack exported as isaaclab_<backend>.cloner.REPLICATION. PhysX pairs physics replication with USD clones (collision groups are authored on the per-env prims; PhysX has no kitless mode), Newton includes USD only under Kit, and OvPhysX replicates alone since its clone replay authors USD. - With replicate_physics=False, cloning is USD-only: the physics engine parses the per-env USD prims directly; an asset whose contexts are all physics-based is simply not cloned. Asset implementations know nothing about cloning beyond registering their cfg; per-asset overrides are a cfg assignment. The per-backend queue_*_replication helpers are removed in favor of this single path.
Summary
InteractiveSceneCfg.replicate_physicsintoReplicateSessionreplicate_physics=FalseProblem
The replication-session refactor in
c7cbe661d07stopped honoringInteractiveSceneCfg.replicate_physics.Before that refactor,
replicate_physics=Falseperformed USD cloning without invoking backend physics replication. After the refactor,InteractiveSceneentered aReplicateSessionthat unconditionally dispatched every queued replication context.This caused scenes explicitly configured with
replicate_physics=Falseto invoke native PhysX replication unexpectedly.Implementation
replicate()andReplicateSessionnow accept areplicate_physicsargument, defaulting toTruefor compatibility with existing callers.Physics replication contexts declare
replicates_physics = True. When physics replication is disabled, those contexts are drained from the queue but not dispatched. USD replication still runs, preserving the complete stage needed for normal physics discovery.PhysX, OVPhysX, and Newton replication contexts are marked consistently.
Validation
347 passed, 41 skippedreplicate_physics=FalseThe runtime-tested patch was applied to the IsaacLab revision pinned by the downstream image. The commit submitted here is an equivalent clean port onto the current
developbranch.Important follow-up
This change restores the intended
replicate_physics=Falsebehavior, but it does not resolve a second issue observed during debugging:With
replicate_physics=True, native PhysX replication of a heterogeneousClonePlan, where different environment rows receive different rigid-object prototypes/configurations, intermittently corrupts native memory under a multi-GPU PhysX + RTX workload. Observed failures include:malloc(): unaligned tcache chunk detecteddouble free or corruptionSIGABRTDisabling only object physics replication eliminated the failure in 4/4 runs, and restoring the scene-level
replicate_physics=Falsepolicy passed another 4/4 runs.This suggests a separate issue in the heterogeneous mGPU physics-replication path. It should be investigated independently; this PR restores the supported opt-out path but does not claim to fix that underlying failure.