Skip to content

OVRTX Correctness#5401

Draft
huidongc wants to merge 4 commits intoisaac-sim:developfrom
huidongc:ovrtx-correctness
Draft

OVRTX Correctness#5401
huidongc wants to merge 4 commits intoisaac-sim:developfrom
huidongc:ovrtx-correctness

Conversation

@huidongc
Copy link
Copy Markdown
Collaborator

Description

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

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (existing functionality will not work without user modification)
  • Documentation update

Screenshots

Please attach before and after screenshots of the change if applicable.

Checklist

  • I have read and understood the contribution guidelines
  • I have run the pre-commit checks with ./isaaclab.sh --format
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • I have updated the changelog and the corresponding version in the extension's config/extension.toml file
  • I have added my name to the CONTRIBUTORS.md or my name already exists there

@huidongc huidongc marked this pull request as draft April 25, 2026 09:08
@github-actions github-actions Bot added the isaac-lab Related to Isaac Lab team label Apr 25, 2026
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab Review Bot

Summary

This PR refactors how simple shading modes are configured in the OVRTX renderer. Instead of a boolean simple_shading_mode config flag, shading modes are now specified via data_types (e.g., "simple_shading_constant_diffuse"). The kernel extract_all_rgba_tiles_kernel is updated to handle 3-channel RGB buffers in addition to 4-channel RGBA. The implementation is mostly correct but has a critical bug in the buffer creation logic.

Architecture Impact

  • Breaking change: Removes OVRTXRendererCfg.simple_shading_mode config option. Users relying on this boolean flag will need to update their configs to use the new data_types-based approach.
  • API change: get_render_var_config() signature changed from (data_types, simple_shading_mode) to just (data_types).
  • The change is self-contained within the isaaclab_ov renderer module.

Implementation Verdict

Significant concerns — One critical bug in buffer creation will cause crashes for simple shading modes.

Test Coverage

No tests are included. For a change that modifies kernel behavior and introduces new data type handling paths, there should be at least:

  • Unit tests verifying correct buffer shapes for each simple shading mode
  • Integration test verifying the kernel correctly extracts 3-channel vs 4-channel data
  • Regression test for the removed simple_shading_mode config (to ensure deprecation is handled)

CI Status

No CI checks available yet.

Findings

🔴 Critical: ovrtx_renderer.py:85-87 — Simple shading buffers created with 3 channels but kernel writes to 4-channel index

The buffer is created with shape (num_envs, height, width, 3):

buffers[simple_shading_type] = wp.zeros((num_envs, height, width, 3), dtype=wp.uint8, device=device)

But in extract_all_rgba_tiles_kernel (ovrtx_renderer_kernels.py:96-97), when num_channels == 4, it writes to index 3:

if num_channels == 4:
    output_buffer[env_idx, y, x, 3] = tiled_buffer[src_y, src_x, 3]

The issue is that for RGB-only mode, the source tiled_buffer from OVRTX's LdrColor is still 4-channel RGBA. The kernel correctly skips writing the alpha channel to the output, but the source buffer indexing tiled_buffer[src_y, src_x, 3] is still valid because it reads from the 4-channel source. This is actually fine.

However, the real bug is that the output buffer shape (num_envs, height, width, 3) doesn't match the kernel's output type annotation wp.array(dtype=wp.uint8, ndim=4). The ndim=4 is correct (4 dimensions), but warp will accept this. Actually let me re-trace this...

Looking more carefully: the buffer has shape (N, H, W, 3) which is indeed ndim=4. The kernel will write to indices [env_idx, y, x, 0], [env_idx, y, x, 1], [env_idx, y, x, 2] and conditionally [env_idx, y, x, 3]. When num_channels=3, index 3 is skipped. This appears correct.

Let me re-check... Actually the logic is correct. Retracting this finding.

🔴 Critical: ovrtx_renderer.py:83-84 — TODO comment left in production code suggests incomplete implementation

# [HDC] TODO:
for simple_shading_type in ...

This TODO comment suggests the author is uncertain about this implementation. The comment should be removed or the concern addressed before merging.

🟡 Warning: ovrtx_usd.py:47-50 — get_render_var_config returns LdrColor for simple shading modes

When a simple shading data type is requested (e.g., "simple_shading_constant_diffuse"), the function get_render_var_config still returns LdrColor as the render var:

use_rgb = any(dt in ["rgb", "rgba"] for dt in data_types)
# simple_shading_* types are not in ["rgb", "rgba"], so use_rgb = False
# ...falls through to...
return "/Render/Vars/LdrColor", "LdrColor", "LdrColor"

This relies on the fact that simple shading modes still output to LdrColor. If this assumption is correct (OVRTX routes minimal mode output to LdrColor), this is fine. If not, the render will produce incorrect output. The code should either:

  1. Document this assumption explicitly, or
  2. Add simple shading types to the use_rgb check

🟡 Warning: ovrtx_renderer.py:475-481 — Fragile buffer key lookup

for k in ["rgba", "simple_shading_constant_diffuse", "simple_shading_diffuse_mdl", "simple_shading_full_mdl"]:
    if k in output_buffers:
        buffer_key = k
        break

This loop gives priority to "rgba" over simple shading types. If a user requests both "rgb" and "simple_shading_constant_diffuse" in data_types, only the rgba buffer will be populated, silently ignoring the simple shading request. This should either:

  1. Be documented as mutual exclusivity, or
  2. Raise an error when conflicting types are requested

🟡 Warning: ovrtx_renderer_cfg.py — Breaking change not documented

The removal of simple_shading_mode: bool is a breaking change for existing users. The PR description doesn't mention migration steps. Users with configs like OVRTXRendererCfg(simple_shading_mode=True) will get TypeError on instantiation.

🔵 Improvement: ovrtx_usd.py:27-39 — _resolve_simple_shading_mode could validate data_types

The function warns on multiple simple shading modes but doesn't prevent mixing simple shading with incompatible types (e.g., ["simple_shading_constant_diffuse", "semantic_segmentation"] where semantic needs different render setup). Consider adding validation or documenting valid combinations.

🔵 Improvement: ovrtx_renderer_kernels.py:83 — Unused num_channels parameter in kernel docstring

The kernel docstring says "Extract ALL RGBA tiles" but now handles RGB too. Consider updating: "Extract ALL RGB/RGBA tiles from a tiled buffer in a single kernel launch."

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented Apr 25, 2026

Greptile Summary

This PR replaces the boolean simple_shading_mode config flag with three explicit data-type strings (simple_shading_constant_diffuse, simple_shading_diffuse_mdl, simple_shading_full_mdl) that map to integer USD render-mode values, and drops SimpleShadingSD in favour of always reading LdrColor from the renderer frame.

  • P1 — silent data loss: In _process_render_frame, the for … break loop selects only the first matching output key from [\"rgba\", \"simple_shading_constant_diffuse\", …]. If rgba and any simple_shading_* type are both present in output_buffers (which _create_warp_buffers allows), the shading buffer is allocated but never written, returning zeroed pixel data with no warning.
  • P2 — dead parameter: _extract_rgba_tiles retains the unused suffix argument while two existing call sites still pass it silently.
  • P2 — personal/debug annotation: The # [HDC] TODO: comment on line 86 of ovrtx_renderer.py should be replaced with a proper issue reference or removed.

Confidence Score: 3/5

Not safe to merge as-is; the P1 logic bug silently produces zeroed output buffers for certain valid data_type combinations.

A confirmed P1 defect (simple_shading buffer silently unpopulated when rgba is also requested) caps the score at 4; the presence of a personal TODO comment and dead parameter evidence that the code is still WIP, pulling the score to 3.

source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py — the _process_render_frame loop logic and _extract_rgba_tiles signature need attention.

Important Files Changed

Filename Overview
source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py Adds 3-channel simple-shading output buffers and refactors process_render_frame to always use LdrColor; contains a P1 logic bug where simple_shading* buffers are silently never populated when rgba is also requested, plus a dead suffix parameter and a personal TODO comment.
source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer_cfg.py Removes the boolean simple_shading_mode config field; clean breaking change with no issues.
source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer_kernels.py Adds num_channels parameter to extract_all_rgba_tiles_kernel to conditionally skip the alpha write for 3-channel buffers; stale inline comment still says (num_envs, H, W, 4).
source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py Replaces boolean simple_shading_mode with a typed integer mode derived from data_types; introduces SIMPLE_SHADING_MODES dict and _resolve_simple_shading_mode helper; docstring for inject_cameras_into_usd still mentions the removed config field.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[data_types from sensor cfg] --> B[get_render_var_config]
    A --> C[_resolve_simple_shading_mode]
    B --> D{depth only?}
    D -- yes --> E[RenderVar: DistanceToImagePlaneSD]
    D -- no --> F{albedo only?}
    F -- yes --> G[RenderVar: DiffuseAlbedoSD]
    F -- no --> H{semantic only?}
    H -- yes --> I[RenderVar: SemanticSegmentation]
    H -- no --> J[RenderVar: LdrColor]
    C --> K{any simple_shading_* in data_types?}
    K -- no --> L[simple_shading_mode = None / RealTimePathTracing]
    K -- yes --> M[simple_shading_mode = int 1/2/3 / Minimal]
    J & L --> N[build_render_scope_usd]
    J & M --> N
    N --> O[USD written to temp file]
    O --> P[OVRTX renderer step]
    P --> Q[frame.render_vars]
    Q --> R{LdrColor in render_vars?}
    R -- yes --> S[loop: find first matching output buffer BREAK at first match]
    S --> T[_extract_rgba_tiles into that buffer only]
    Q --> U{DistanceToImagePlaneSD / DepthSD?}
    U -- yes --> V[_extract_depth_tiles]
    Q --> W{DiffuseAlbedoSD?}
    W -- yes --> X[_extract_rgba_tiles albedo]
    Q --> Y{SemanticSegmentation?}
    Y -- yes --> Z[_extract_rgba_tiles semantic]
Loading

Comments Outside Diff (3)

  1. source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py, line 429-435 (link)

    P2 Dead suffix parameter

    The suffix parameter is accepted by _extract_rgba_tiles but is never used in the function body. It was likely carried over from the old call sites that passed suffix="rgb", suffix="albedo", and suffix="semantic". Two of the three remaining call sites still pass suffix=... (lines 504 and 528), resulting in silently ignored arguments.

  2. source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer_kernels.py, line 79 (link)

    P2 Stale type-hint comment

    The inline comment (num_envs, H, W, 4) is now incorrect since this PR enables 3-channel (RGB) output buffers to be passed here. Consider updating to (num_envs, H, W, C) where C is 3 or 4.

  3. source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_usd.py, line 127 (link)

    P2 Stale docstring references removed field

    cfg: OVRTX renderer config (simple_shading_mode, temp_usd_dir, temp_usd_suffix). still mentions simple_shading_mode, which was removed from OVRTXRendererCfg in this PR.

Reviews (1): Last reviewed commit: "draft" | Re-trigger Greptile

Comment thread source/isaaclab_ov/isaaclab_ov/renderers/ovrtx_renderer.py Outdated
Comment on lines +477 to +487
buffer_key = None

for k in ["rgba", "simple_shading_constant_diffuse", "simple_shading_diffuse_mdl", "simple_shading_full_mdl"]:
if k in output_buffers:
buffer_key = k
break

if buffer_key is not None:
with frame.render_vars["LdrColor"].map(device=Device.CUDA) as mapping:
tiled_data = wp.from_dlpack(mapping.tensor)
self._extract_rgba_tiles(render_data, tiled_data, output_buffers, buffer_key)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 simple_shading_* buffer silently unpopulated when rgba is also requested

The loop breaks at the first matching key, so if both "rgba" and "simple_shading_constant_diffuse" appear in output_buffers, only "rgba" is written; the simple-shading buffer is left as all zeros with no warning. Since _create_warp_buffers allocates both buffers independently, and _resolve_simple_shading_mode happily returns a non-None mode even when "rgba" is also present, a caller that requests ["rgba", "simple_shading_constant_diffuse"] gets a zeroed output for the shading channel they asked for.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

But the renderer won't returned simple shading together with regular color shading. Their relationship is A or B, but not A and B.

@huidongc huidongc force-pushed the ovrtx-correctness branch from 305ff26 to cbdb93f Compare April 25, 2026 11:00
Copy link
Copy Markdown

@isaaclab-review-bot isaaclab-review-bot Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 Isaac Lab Review Bot

Summary

This PR refactors the OVRTX renderer's shading mode configuration, replacing the boolean simple_shading_mode config option with explicit support for three RTX minimal rendering modes (simple_shading_constant_diffuse, simple_shading_diffuse_mdl, simple_shading_full_mdl) specified through the existing data_types list. It also fixes the RGB tile extraction kernel to handle 3-channel outputs correctly.

Architecture Impact

Medium impact. This is a breaking change to OVRTXRendererCfg — the simple_shading_mode field is removed. Any existing code setting OVRTXRendererCfg(simple_shading_mode=True) will fail at runtime with an AttributeError. The change also removes support for the SimpleShadingSD render variable, replacing it with LdrColor for all cases. This affects how OVRTX renders frames when minimal modes are requested.

Implementation Verdict

Minor fixes needed — The core logic is sound, but there's one correctness bug in the frame processing logic and the breaking API change needs documentation.

Test Coverage

The isaaclab_ov CI passed, indicating existing tests still work. However, there are no new tests for the three new RTX minimal modes, and no regression tests verifying that the old simple_shading_mode=True behavior is preserved through the new interface. Given this is a bug fix PR (per the description), regression tests should be present.

CI Status

isaaclab_ov passed. Other tests skipped (expected for this module). pre-commit passed.

Findings

🔴 Critical: ovrtx_renderer.py:520-536 — SimpleShadingSD render variable support silently removed
The old code checked for SimpleShadingSD in frame.render_vars and used it when available. The new code only checks for LdrColor. If OVRTX returns SimpleShadingSD (which it does in Minimal mode based on the removed get_render_var_config logic), the new code will silently fail to extract the frame data because "LdrColor" in frame.render_vars may be False.

# Old code handled both:
rgb_render_var = "SimpleShadingSD" if "SimpleShadingSD" in frame.render_vars else "LdrColor" ...

# New code only checks LdrColor:
if "LdrColor" in frame.render_vars:  # What if OVRTX returns SimpleShadingSD instead?

Verify that OVRTX actually returns LdrColor when omni:rtx:rendermode = "Minimal" is set, or restore the fallback logic.

🟡 Warning: ovrtx_renderer_cfg.py — Breaking API change without deprecation
The simple_shading_mode field was removed entirely. Per Isaac Lab contribution guidelines, breaking changes to public config classes should include deprecation warnings or migration guidance. Users with existing configs will get unhelpful AttributeError instead of a clear migration message.

# Before: OVRTXRendererCfg(simple_shading_mode=True)
# After: Must use data_types=["simple_shading_constant_diffuse"] instead

Consider adding a __post_init__ check that raises a clear error if the old field is detected.

🟡 Warning: ovrtx_usd.py:32-33 — Removed SimpleShadingSD path from get_render_var_config
The function no longer returns the SimpleShadingSD render variable configuration. This is inconsistent with the stated goal of supporting minimal shading modes. The render var should match what OVRTX expects when minimal mode is active.

# Removed:
if simple_shading_mode:
    return "/Render/Vars/SimpleShading", "SimpleShading", "SimpleShadingSD"

If minimal modes use LdrColor as the output variable, this is correct but undocumented.

🔵 Improvement: ovrtx_renderer.py:78-95 — _resolve_simple_shading_data_type could be clearer
The function filters data_types to find RTX minimal modes but doesn't document that the order in data_types determines precedence. The behavior of "using the first in the list" may surprise users since list order is often considered arbitrary.

def _resolve_simple_shading_data_type(data_types: list[str]) -> str | None:
    # Consider: document or use explicit priority instead of list order

🔵 Improvement: ovrtx_renderer_kernels.py:94 — Docstring mentions treating invalid num_channels as 3
The docstring says "If a value other than 3 or 4 is given, it will be treated as 3 (RGB)" but the kernel doesn't validate this — the calling code does (line 483-484 in ovrtx_renderer.py). The docstring is misleading about where validation happens.

# Line 94: "If a value other than 3 or 4 is given, it will be treated as 3 (RGB)."
# But actual behavior: ValueError raised at ovrtx_renderer.py:484

🔵 Improvement: ovrtx_renderer.py:116-135 — Buffer creation adds empty lines inconsistently
The added blank lines improve readability but the style is inconsistent with the rest of the codebase. Minor, but noted.

1. test_rendering_correctness.py: contains all backend combinations that require Kit / SimulationApp
2. test_rendering_correctness_kitless.py: contains the other backend combinations

Shared methods between these two functions are moved to rendering_correctness_test_utils.py
@pbarejko pbarejko self-requested a review April 28, 2026 01:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

isaac-lab Related to Isaac Lab team

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant