Skip to content

Latest commit

Β 

History

History
272 lines (203 loc) Β· 13.9 KB

migration-4-5.md

File metadata and controls

272 lines (203 loc) Β· 13.9 KB

physx-sys 4.1 -> 5.1 migration guide

This is a migration guide for the physx-sys crate from the version (0.8.*) that was wrapping PhysX SDK 4.1, and the version (0.10) that transition to PhysX SDK 5.1.3. (see PR#183 for the PR that actually made a bulk of the transition)

Note that there is a migration guide from NVidia for the C++ code here.

General Changes

pxbind

The pxbind program, used to query the C++ AST and generate both the FFI binding functions in Rust and their C++ implementation, as well as the structgen program used to generate the POD types used on both sides of the FFI boundary, has been rewritten from C++ to Rust. This was done to get rid of the annoying dependency on libclang and just...not have C++ code that had bitrotted since the original implementation. Transitioning to Rust means it should be easier for contributors to make changes to the binding generation and just iterate on and improve the generated binding code. This change is not directly visible to end users of the crate, it is just mentioned since it makes up a large part of the new code in PR#183.

Enums

Enums exposed by physx-sys have been changed to be more Rust like. We'll use PxShapeFlag to illustrate the changes.

Old enum output

pub mod PxShapeFlag{
pub type Enum = u32;
pub const eSIMULATION_SHAPE: Enum = 1u64 as u32;
pub const eSCENE_QUERY_SHAPE: Enum = 2u64 as u32;
pub const eTRIGGER_SHAPE: Enum = 4u64 as u32;
pub const eVISUALIZATION: Enum = 8u64 as u32;
}

New enum output

/// Flags which affect the behavior of PxShapes.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[repr(i32)]
pub enum PxShapeFlag {
    /// The shape will partake in collision in the physical simulation.
    ///
    /// It is illegal to raise the eSIMULATION_SHAPE and eTRIGGER_SHAPE flags.
    /// In the event that one of these flags is already raised the sdk will reject any
    /// attempt to raise the other.  To raise the eSIMULATION_SHAPE first ensure that
    /// eTRIGGER_SHAPE is already lowered.
    ///
    /// This flag has no effect if simulation is disabled for the corresponding actor (see [`PxActorFlag::eDISABLE_SIMULATION`]).
    SimulationShape = 1,
    /// The shape will partake in scene queries (ray casts, overlap tests, sweeps, ...).
    SceneQueryShape = 2,
    /// The shape is a trigger which can send reports whenever other shapes enter/leave its volume.
    ///
    /// Triangle meshes and heightfields can not be triggers. Shape creation will fail in these cases.
    ///
    /// Shapes marked as triggers do not collide with other objects. If an object should act both
    /// as a trigger shape and a collision shape then create a rigid body with two shapes, one being a
    /// trigger shape and the other a collision shape. It is illegal to raise the eTRIGGER_SHAPE and
    /// eSIMULATION_SHAPE flags on a single PxShape instance.  In the event that one of these flags is already
    /// raised the sdk will reject any attempt to raise the other.  To raise the eTRIGGER_SHAPE flag first
    /// ensure that eSIMULATION_SHAPE flag is already lowered.
    ///
    /// Trigger shapes will no longer send notification events for interactions with other trigger shapes.
    ///
    /// Shapes marked as triggers are allowed to participate in scene queries, provided the eSCENE_QUERY_SHAPE flag is set.
    ///
    /// This flag has no effect if simulation is disabled for the corresponding actor (see [`PxActorFlag::eDISABLE_SIMULATION`]).
    TriggerShape = 4,
    /// Enable debug renderer for this shape
    Visualization = 8,
}

Enum differences

  1. Enums are now regular Rust enums, rather than modules.
  2. Enum variants now named in UpperCamelCase like standard Rust enum variants (minus the e suffix)
  3. Enums now have the documentation for the enum itself, as well as each variant, pulled from the C++ declaration

Migrating enums

Migrating enums is trivial in most cases as it is just a matter of renaming the variant from the C++ name to the new form. In the case the type itself is used, it's just a matter of removing the ::Enum from the type.

PxShape_setFlag_mut(
    shape,
-   PxShapeFlag::eVISUALIZATION,
+   PxShapeFlag::Visualization,
    enable_physics_shape_debug_rendering,
);

-fn is_flag_enabled(shape: *const PxShape, flag: PxShapeFlag::Enum) -> bool {
+fn is_flag_enabled(shape: *const PxShape, flag: PxShapeFlag) -> bool {

One wrinkle with this new form is that converting to and from integer types is not as easy. If this is problematic we can add generation of From for 1 or more integer types for enums.

Flags

PhysX uses bitsets fairly heavily in the API, using PxFlags<_enum_type_, _integer_type_> to create wrappers for an enum. We'll use PxShapeFlags, the flags version of PxShapeFlag.

Old flags output

#[derive(Clone, Copy)]
#[repr(C)]
pub struct PxShapeFlags{
    pub mBits: u8,
}

New flags output

bitflags::bitflags! {
    /// Flags for [`PxShapeFlag`]
    #[derive(Default)]
    #[repr(transparent)]
    pub struct PxShapeFlags: u8 {
        const SimulationShape = 1 << 0;
        const SceneQueryShape = 1 << 1;
        const TriggerShape = 1 << 2;
        const Visualization = 1 << 3;
    }
}

Flags differences

  1. Flags now create a bitflags backed bitset, using a transparent repr using the same sized integer as in C++, allowing for transparent usage across the FFI boundary.
  2. Normal bitset operations are now generated by bitflags
  3. As with enums, each flag variant is named in UpperCamelCase

Migrating flags

Since the generated *Flags bitset has all of the bitset operations the migrated code should be much cleaner as there is no longer a need to convert to the underlying integer type.

-let mut shape_flags = PxShapeFlags {
-    mBits: (PxShapeFlag::eSCENE_QUERY_SHAPE | PxShapeFlag::eVISUALIZATION) as u8,
-};
+let mut shape_flags = PxShapeFlags::SceneQueryShape | PxShapeFlags::Visualization;

if config.trigger_volume {
-    shape_flags.mBits |= PxShapeFlag::eTRIGGER_SHAPE as u8;
+    shape_flags |= PxShapeFlags::TriggerShape;
} else {
-    shape_flags.mBits |= PxShapeFlag::eSIMULATION_SHAPE as u8;
+    shape_flags |= PxShapeFlags::SimulationShape;
}

PxPhysics_createShape_mut(
    px_physics.as_mut_ptr(),
    geom.geometry.as_ptr(),
    config.material,
    is_exclusive,
    shape_flags,
)

Structs

The only difference, other than actual changes in the C++ classes/structs themselves, is that we now expose the debug-structs feature, which enables Debug to be derived for all of the generated POD structs. This is not enabled by default as the compile time and binary size increases are generally not going to be worthwhile in normal usage.

#[derive(Clone, Copy)]
#[cfg_attr(feature = "debug-structs", derive(Debug))]
#[repr(C)]
pub struct PxActorShape {
    pub actor: *mut PxRigidActor,
    pub shape: *mut PxShape,
}

Functions

Static methods are now no longer suffixed with _mut.

-fn PxArticulationReducedCoordinate_setSolverIterationCounts_mut();
+fn PxArticulationReducedCoordinate_setSolverIterationCounts();

All generated Rust functions now include the comments from the C++ code, for convenience.

-pub fn PxRigidDynamic_getKinematicTarget(self_: *const PxRigidDynamic, target: *mut PxTransform, ) -> bool;
+/// Get target pose of a kinematically controlled dynamic actor.
+///
+/// True if the actor is a kinematically controlled dynamic and the target has been set, else False.
+pub fn PxRigidDynamic_getKinematicTarget(self_: *const PxRigidDynamic, target: *mut PxTransform) -> bool;

Other

One other change of note is that the old pxbind was incorrectly binding unsigned long long/uint64_t to usize. It is now bound to u64. This would also apply to i64, but there are no instances of this in the public PhysX API.

Functions that don't return anything no longer specify the return type as -> ().

API Changes

This section contains API changes in the C++ code that are reflected in the API exposed by this crate. This is not exhaustive, as there are frankly too many changes both trivial and large to document here. That being said, please submit PRs to improve this section if you run up against issues when migrating from the 4.1 based crate to the 5.1 based crate that you think make sense to document.

If you want an exhaustive listing of API changes you can use cargo public-api

cargo install --locked cargo-public-api
cd physx-rs/physx-sys
cargo public-api --simplified diff 0.8.2

It's also recommended to checkout the PhysX CHANGELOG though note that this is also not exhaustive!

Embark Changes

While most of the API changes are just reflecting the changes in the underlying C++ code, we've also made a few changes to how we generate bindings.

  • We no longer bind the math functions from PxMath.h, there is no functionality there that cannot be done in pure Rust, without crossing the FFI boundary
  • We no longer bind the functions from PxString.h, PxUtilities.h, PxAtomic.h or PxHash.h, these are all APIs that though "public" are really only used inside C++ itself

Deprecated

One major change from the old bindings is that deprecated items (classes/structs/typedefs/enum variants/fields/functions/methods) are now not generated. This means some items that were already deprecated in the 4.1 SDK or no longer present, in addition to items that were deprecated in the transition from 4.1 -> 5.1.

We also abuse the PX_DEPRECATED macro to remove items that we intentionally don't expose in this crate, notably some of the new features added in 5.1 like soft bodies and cloth which are only available on NVidia GPUs and whose source is not part of the open source SDK.

If you were using an API in the former crate that is now deprecated (check here) you can open a PR to un-deprecate the item (if it makes sense).

Notable Deprecations

  • Vehicles: All of the former Vehicle SDK components were deprecated and replaced with new APIs. These are not bound yet, see #186
  • PxCooking: Deprecated and replaced with lower level individual functions/classes. This is temporarily un-deprecated but will be replaced later, see #187
  • Joint Projections: get/setProjectionAngular/LinearTolerance have been deprecated in all joints

PxRefCounted

In PhysX 4 many classes had their own release, getReferenceCount and acquireReference methods. These methods have now all been moved to PxRefCounted, a new base class in PhysX 5. So now you will use those PxRefCounted_* methods instead of the former class methods, casting the pointer to a PxRefCounted.

-PxMaterial_release(material);
+PxRefCounted_release(material.cast());
  • PxMaterial
  • PxShape
  • PxConvexMesh
  • PxHeightField
  • PxTriangleMesh

Removed

Several APIs were completely removed, with their functionality either going away, or being absorbed into other classes.

  • PxArticulationBase and PxArticulation were completely removed, most functionality was moved to PxArticulationReducedCoordinate
  • PxArticulationJointBase and PxArticulationJoint were completely removed, most functionality was moved to PxArticulationJointReducedCoordinate
  • PxBatchQueryDesc has been removed
  • PxBatchQueryMemory has been removed

Renamed

Replaced/Moved

  • PxBatchQuery has been replaced by PxBatchQueryExt
  • PxScene queries have mostly been moved to PxSceneQueryExt
  • PxRigidBody_setAngularVelocity_mut and PxRigidBody_setLinearVelocity_mut have been moved to PxRigidDynamic
  • Many class constructors have been consolidated, so instead of having, for example, a default constructor and a constructor that takes two f32 parameters, there will now be single constructor that takes two f32 parameters, both having default values that used to be set in the default constructor. If you were calling a _new function (a wrapper for a constructor) that now fails since the signature is different, you can look at the code to determine what arguments to pass to retain the default constructor behavior.
-pub fn PxCapsuleGeometry_new() -> PxCapsuleGeometry;
+pub fn PxCapsuleGeometry_new(radius_: f32, halfHeight_: f32) -> PxCapsuleGeometry;