Skip to content

Commit f1358cc

Browse files
Fix OVPhysX device routing for CPU-resident tensor types
_CPU_ONLY_TYPES omitted eight tensor types that are CPU-resident even on a GPU simulation: the articulation and rigid-body collision-shape contact and rest offsets, both gravity-disable flags, and the DOF drive type and drive model. Because _native_device consults this set, it returned the simulation device for host-resident data. Every access staged a hidden host-to-device copy on a path the view believed was device-native, and _check_device rejected a buffer placed on the host, where the data actually lives, with DeviceMismatch. Residency was measured rather than assumed: ovphysx exposes no residency query, so each type was classified by counting CUDA memcpys around a binding read into a host buffer and into a device buffer, under the DirectGPU configuration isaaclab_ov itself sets. All eight measured CPU-resident across every GPU sample scene in the ovphysx wheel, and all previously classified members measured as declared. The guarding test compared the view's derived set against the canonical set it is derived from, so it could not fail for any contents. It now asserts against an independent inventory of measured residency, mirroring the existing _EXPECTED_READ_ONLY_NAMES pattern, so an incomplete set is caught.
1 parent b44ea65 commit f1358cc

3 files changed

Lines changed: 72 additions & 2 deletions

File tree

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
Fixed
2+
^^^^^
3+
4+
* Fixed :class:`~isaaclab_ov.sim.views.OvPhysxView` routing eight CPU-resident
5+
tensor types to the simulation device. The per-collision-shape contact and rest
6+
offsets, the articulation and rigid-body gravity-disable flags, and the DOF drive
7+
type and drive model are CPU-resident even on a GPU simulation, but were absent
8+
from the internal CPU-only classification. Reads and writes of these types
9+
incurred a hidden per-call host-to-device staging copy, and a correctly placed
10+
host buffer was rejected with ``OvPhysxView.DeviceMismatch``. Residency was
11+
measured on a GPU simulation by counting CUDA memcpys around a binding read.

source/isaaclab_ov/isaaclab_ov/tensor_types.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,17 @@
442442
RIGID_BODY_MASS,
443443
RIGID_BODY_COM_POSE,
444444
RIGID_BODY_INERTIA,
445+
# Collision-shape offsets, gravity-disable flags and DOF drive metadata. Measured
446+
# CPU-resident on a GPU sim; referenced through ``_TT`` since this module exposes
447+
# no public alias for them.
448+
_TT.ARTICULATION_DOF_DRIVE_TYPE,
449+
_TT.ARTICULATION_DOF_DRIVE_MODEL,
450+
_TT.ARTICULATION_BODY_DISABLE_GRAVITY,
451+
_TT.ARTICULATION_CONTACT_OFFSET,
452+
_TT.ARTICULATION_REST_OFFSET,
453+
_TT.RIGID_BODY_DISABLE_GRAVITY,
454+
_TT.RIGID_BODY_CONTACT_OFFSET,
455+
_TT.RIGID_BODY_REST_OFFSET,
445456
DEFORMABLE_MATERIAL_DYNAMIC_FRICTION,
446457
DEFORMABLE_MATERIAL_YOUNGS_MODULUS,
447458
DEFORMABLE_MATERIAL_POISSONS_RATIO,

source/isaaclab_ov/test/sim/test_ovphysx_view.py

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,48 @@
7070
}
7171
)
7272

73+
# CPU-resident on a GPU sim. Each name was measured, not assumed: with DirectGPU
74+
# (``suppressReadback=True``) the residency of every tensor type was determined by counting
75+
# CUDA memcpys around a binding read into a host buffer and into a device buffer.
76+
_EXPECTED_CPU_ONLY_NAMES = frozenset(
77+
{
78+
"articulation_body_com_pose",
79+
"articulation_body_disable_gravity",
80+
"articulation_body_inertia",
81+
"articulation_body_inv_inertia",
82+
"articulation_body_inv_mass",
83+
"articulation_body_mass",
84+
"articulation_contact_offset",
85+
"articulation_dof_armature",
86+
"articulation_dof_damping",
87+
"articulation_dof_drive_model",
88+
"articulation_dof_drive_type",
89+
"articulation_dof_friction_properties",
90+
"articulation_dof_limit",
91+
"articulation_dof_max_force",
92+
"articulation_dof_max_velocity",
93+
"articulation_dof_stiffness",
94+
"articulation_rest_offset",
95+
"articulation_shape_friction_and_restitution",
96+
"deformable_material_bending_damping",
97+
"deformable_material_bending_stiffness",
98+
"deformable_material_dynamic_friction",
99+
"deformable_material_elasticity_damping",
100+
"deformable_material_poissons_ratio",
101+
"deformable_material_thickness",
102+
"deformable_material_youngs_modulus",
103+
"rigid_body_com_pose",
104+
"rigid_body_contact_offset",
105+
"rigid_body_disable_gravity",
106+
"rigid_body_inertia",
107+
"rigid_body_inv_inertia",
108+
"rigid_body_inv_mass",
109+
"rigid_body_mass",
110+
"rigid_body_rest_offset",
111+
"rigid_body_shape_friction_and_restitution",
112+
}
113+
)
114+
73115
# Per-type shapes used by the fakes (only the types touched by the tests).
74116
_SHAPES = {
75117
TensorType.RIGID_BODY_POSE: lambda n: (n, 7),
@@ -204,15 +246,21 @@ def test_read_only_and_cpu_only_classification():
204246
assert not is_read_only("articulation_dof_stiffness")
205247
assert is_cpu_only("articulation_dof_stiffness")
206248
assert is_cpu_only("rigid_body_mass")
249+
assert is_cpu_only("rigid_body_disable_gravity")
250+
assert is_cpu_only("articulation_dof_drive_type")
207251
assert not is_cpu_only("rigid_body_pose")
208252

209253

210254
def test_cpu_only_names_match_canonical_set():
211-
# The view derives its CPU-only set from tensor_types so the two cannot drift.
255+
# Comparing the view's derived set against the canonical one cannot fail, since the
256+
# former is built from the latter. The expected inventory is what gives this test
257+
# teeth: it is measured residency, so it also rejects a set that is merely incomplete.
212258
from isaaclab_ov.sim.views import ovphysx_view as mod
213259
from isaaclab_ov.tensor_types import _CPU_ONLY_TYPES
214260

215-
assert frozenset(tt.name.lower() for tt in _CPU_ONLY_TYPES) == mod._CPU_ONLY_NAMES
261+
assert frozenset(tt.name.lower() for tt in _CPU_ONLY_TYPES) == _EXPECTED_CPU_ONLY_NAMES
262+
assert mod._CPU_ONLY_NAMES == _EXPECTED_CPU_ONLY_NAMES
263+
assert set(attribute_vocabulary()) >= mod._CPU_ONLY_NAMES
216264

217265

218266
# -----------------------------------------------------------------------------

0 commit comments

Comments
 (0)