Waits for textures to be loaded for Isaac RTX renderer#4956
Waits for textures to be loaded for Isaac RTX renderer#4956bareya wants to merge 11 commits intoisaac-sim:developfrom
Conversation
Greptile SummaryThis PR replaces a long-standing workaround (running 5 fixed simulation steps to allow textures to load) with a proper event-driven mechanism that subscribes to the Carb Key changes:
Issues found:
Confidence Score: 3/5
Important Files Changed
Sequence DiagramsequenceDiagram
participant Cam as Camera/TiledCamera
participant Utils as isaac_rtx_renderer_utils
participant Carb as carb.eventdispatcher
participant App as omni.kit.app
Cam->>Utils: ensure_isaac_rtx_render_update()
Utils->>Utils: check dedup key (id(sim), step_count)
Utils->>Carb: _ensure_streaming_subscription() [idempotent]
Carb-->>Utils: subscription handle
Utils->>App: app.update() [trigger RTX render]
App-->>Carb: fires streaming_status(isBusy=True)
Carb-->>Utils: _on_streaming_status_event → _streaming_is_busy=True
Utils->>Utils: if _streaming_is_busy → _wait_for_streaming_complete()
loop Until idle or 30s timeout
Utils->>App: app.update()
App-->>Carb: fires streaming_status(isBusy=False)
Carb-->>Utils: _on_streaming_status_event → _streaming_is_busy=False
end
Utils->>Utils: update _last_render_update_key
Utils-->>Cam: return (textures ready)
Last reviewed commit: fc40398 |
| _streaming_is_busy: bool = False | ||
| _streaming_subscription = None | ||
| _streaming_subscribed: bool = False |
There was a problem hiding this comment.
Stale streaming state across SimulationContext instances
_streaming_is_busy and _streaming_subscribed are module-level globals that are never reset when a new SimulationContext is created. The render-update dedup key (_last_render_update_key) correctly invalidates itself per-context via id(sim), but the streaming state has no equivalent invalidation.
The problematic scenario: if a previous simulation ends while _streaming_is_busy = True (i.e., the 30 s timeout was hit), the next test's first call to ensure_isaac_rtx_render_update() will skip _ensure_streaming_subscription() (already subscribed) then immediately enter _wait_for_streaming_complete() because the stale True flag is never cleared between contexts. This could add an unnecessary second full timeout wait at the start of every subsequent test in a test suite.
Consider resetting the streaming state alongside the dedup key when a new SimulationContext is detected:
# at the top of ensure_isaac_rtx_render_update(), after computing `key`
if key[0] != _last_render_update_key[0]: # new SimulationContext
global _streaming_is_busy, _streaming_subscribed, _streaming_subscription
_streaming_is_busy = False
_streaming_subscribed = False
_streaming_subscription = NoneThere was a problem hiding this comment.
Good point! Thanks AI!
| def _ensure_streaming_subscription() -> None: | ||
| """Subscribe to RTX streaming status events (idempotent).""" | ||
| global _streaming_subscription, _streaming_subscribed | ||
| if _streaming_subscribed: | ||
| return | ||
|
|
||
| _streaming_subscribed = True | ||
| try: | ||
| from carb.eventdispatcher import get_eventdispatcher | ||
|
|
||
| dispatcher = get_eventdispatcher() | ||
| if dispatcher is not None: | ||
| _streaming_subscription = dispatcher.observe_event( | ||
| observer_name="isaaclab_rtx_streaming_wait", | ||
| event_name=_RTX_STREAMING_STATUS_EVENT, | ||
| on_event=_on_streaming_status_event, | ||
| ) | ||
| except (ImportError, AttributeError): | ||
| pass |
There was a problem hiding this comment.
_streaming_subscribed guard set before subscription succeeds
_streaming_subscribed = True is written on line 52 before the try block verifies that a dispatcher is available and the subscription actually succeeds. If get_eventdispatcher() returns None (or raises and is silently caught), _streaming_subscribed is permanently True, meaning no retry will ever be attempted — even though _streaming_subscription remains None and no events will ever arrive.
The result is that the texture-wait feature silently degrades to a no-op without any log message, making it hard to diagnose why textures are still black in environments where the event dispatcher is slow to initialise.
Consider either:
- Moving
_streaming_subscribed = Trueto after a successfulobserve_event()call, or - Logging a warning when the dispatcher is unavailable.
| def _wait_for_streaming_complete() -> None: | ||
| """Pump ``app.update()`` until RTX streaming reports idle or timeout.""" | ||
| import omni.kit.app | ||
|
|
||
| start = time.monotonic() | ||
| while _streaming_is_busy and (time.monotonic() - start) < _STREAMING_WAIT_TIMEOUT_S: | ||
| omni.kit.app.get_app().update() |
There was a problem hiding this comment.
No rate-limiting in the busy-wait loop
_wait_for_streaming_complete() calls omni.kit.app.get_app().update() in a tight loop with no time.sleep() between iterations. While each app.update() call does real work, it can return quickly in headless/test configurations, turning this into a CPU-intensive spin for up to 30 seconds in the timeout scenario.
Consider adding a small sleep to yield the CPU between pumps:
while _streaming_is_busy and (time.monotonic() - start) < _STREAMING_WAIT_TIMEOUT_S:
omni.kit.app.get_app().update()
time.sleep(0.005) # ~200 Hz max pump rateThere was a problem hiding this comment.
i don't think we need to add overhead of sleep here, even small. if something is timing out no need to optimize the exit IMO
5b51550 to
8704770
Compare
Wait for all textures to load in IsaacRTX Renderer for Camera and Tiled Camera
Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context.
List any dependencies that are required for this change.
Fixes # (issue)
Type of change
Screenshots
Please attach before and after screenshots of the change if applicable.
Checklist
pre-commitchecks with./isaaclab.sh --formatconfig/extension.tomlfileCONTRIBUTORS.mdor my name already exists there