Skip to content

2021.10.07

performance

Highlight for this release is Performance, and is part 2/4 of the new Markers.

Showcase

You know the drill, we'll start with some eye candy. 🍬

New Shading

Now more like actual candy. Nom nom nom!

image

Raining Ragdolls

Quick! Get inside!

Do the Robot

Model and Rig courtesy of Amedeo Beratta

Vehicular Render

Made by @tris

Guide Space Mania

Oh the trickery you can get up to. 🥳


Anniversary

That's right! Ragdoll turned 1 this week! 🥳

In my original business plan, I had written..

"Revenue, year 1: £20,000"

..which was blissfully optimistic. However! I'm happy to say that Ragdoll blew past this in the first 6 days into launch, on the 28th of July this year. Very few startups achieve this amount of revenue in year 1; the vast majority achieve £0 for the first number of years (I watch a lot of Dragon's Den 😅), the expectation being that they will regain their investment once enough value has been created. But given we're past this point already, this to me is validation that you want this.

So, let's keep it going, shall we? :)


Manikin Rig

Throughout these notes, I'll be using this guy here. Feel free to download and play around with it.

image


Performance

This release was all about performance, so how did we do?

In short, very well! We're now a lot closer to the capabilities of your hardware with a lot less waste. Because you see, software development is a lot like Jenga. You start off with a tower full of bricks, but every brick adds to the overall weight of the tower. And not every brick is necessary to keep it standing. The Eiffel Tower is an example of what a structure can look like with the absolute minimal amount of material. It is an optimal shape; anything added is wasted weight, anything removed would sacrifice stability. That is the structure we've been working towards with this release.

In terms of time spent, Ragdoll has three stages.

# Stage Description
1 Evaluation This is primarily your character rig - the transform hierarchy, constraints, any deformers, and so forth. It is how data is passed from Maya into Ragdoll.
2 Simulation Once data has been aquired, Ragdoll considers all of it and applies forces, solves constraints, contacts, that kind of thing.
3 Rendering Finally, we need pixels. In the case of Ragdoll, this means generating and uploading geometry to the GPU; including capsules but also your meshes which are converted into "convex hulls".

Simulation has always been fast and in the previous release, we focused entirely on workflow which had an indirect impact on Evaluation and Rendering. One got faster, but the other got slower.

image

Changes in Part ¼

Let's recap what happened in the previous release.

We tackled Evaluation which boosted performance by 2-10x by unlocking parallelism. Before, the better your character rig benefited from multithreading the worse it would perform with Ragdoll. Ragdoll would force any control you simulated into serial evaluation - to compute one after another - because the solver was fundamentally single-threaded.

With Markers, Ragdoll separated from the overall rig evaluation, which meant (1) your rig can continue running in parallel and (2) Ragdoll could also run in parallel.

Consider this example.

Rigids Markers
before after

This is how Maya scheduled evaluation for this scene with Rigid versus Marker. To the left, everything runs one after the other. It's terrible. To the right, every box is evaluated in parallel. Which means the more boxes and cores you have, the better utilisation you get.

The scene itself is very simple, it's this one here.

So evaluation got faster, but rendering got slower. All-in-all we gained about 100% performance.

With this release, we'll tackle that rendering block. Let's have a look at what's changed, in order of most-to-least significance.

Topic Savings Description
Less CPU to GPU communication 1550x More buffers, less uniforms
Connection Monitoring 40x Less dependence on time, more on physical connections being made and unmade
Change Monitoring 40x Ignore anything that hasn't actually changed
Less Dirty Propagation 3x Less of a shotgun blast, more like a sniper


CPU to GPU Communication

The previous release, and each one before it, had 1 shader per rigid. In the case of 600 rigid bodies, that meant 600 shaders. 600 shaders means 600 parameter updates of primarily color and 600 unique draw calls.

On top of this, all geometry was regenerated and re-uploaded to the GPU on every frame. Robust, but not very fast.

This release consolidates all shaders into one, colors are uploaded only once alongside their geometry and rendered using a custom GLSL shader (i.e. OpenGL 3.3).

What about DirectX?

If you are on Windows and can't use OpenGL for whichever reason, there is backwards compatibility built-in.

from ragdoll import options
options.write("useShaders", False)

Or via the Ragdoll Preferences.

image

Bearing in mind this will cost you 50% of the rendering performance and won't benefit from future shading related features and improvements. The option will remain until it's clear whether and how much it is actually used. (Let us know in the chat!)

Let's have a look at how this change affects your overall experience.

Before (7fps)

After (130 fps)

A closer look reveals exactly where this improvement comes from.

Before

This block is what we control, it's the Ragdoll rendering pipeline taking a whopping 93 ms per refresh.

image

After

With this release, this number dropped to 0.06ms (58 microseconds) that's an improvement of 1550x (!).

image

What about the other blocks?

The bottleneck has now moved to that green one and all of those blue, and those are Maya's internal rendering pipeline.

There isn't much we can do to directly impact it; it's mostly out of our hands. However, by massaging our data more and making life easier for Maya it should be possible to reduce these as well.

See Future Work for details on next steps, and if this is something you, fellow reader, is familiar with do get in touch!

Finally, as a result of having complete control over the shader running on the GPU, we're now able to more intimately design it to look the way we want. Expect more refinements here over time.

Before After
image image


Connection & Change Monitoring

In the previous release, and all versions of Ragdoll so far, we've tasked Maya with evaluating every plug on every frame, including the heavy-duty plugs between Rigid Body -> Solver.

Here's what this felt like in a scenario of 600 unique objects.

Before (5 fps)

Painful! The reason is because even though we're only moving a single box, Ragdoll checks-in with all other boxes too.

After (90 fps)

Blissful. In this case, only one of the boxes is actually updated, as one would expect.

Let's have a closer look at where performance is going here.

Before

Oh that's ghastly. Not only does it spend time evaluating all of those boxes, but it's making the solver take much longer consolidating the results taking a whopping 56 ms.

image

After

Whereas now, as one would expect, we're only evaluating this one box in a total of 0.7ms, resulting in a performance improvement 80x.

image

That looks like 3?

And that's true, it still makes three separate calls to this one box. Which means there's more room to optimise here, and we'll get there.

Needless to say, this happened before as well but was obscured by how many calls there actually are. Luckily, at least two of these calls happen in parallel.

600 capsules

The current framerate on 600 unique objects, something for future Ragdoll to try and compete with. For reference, an average ragdoll consists of about 20-30 objects.


Future Work

There is at least 4-16x performance left on the table for specialised cases.

Work Savings Benefit
Optimised Render Items 4x Native Maya still renders 4x faster than us, which means there's more things we can do.
Instancing for Rendering 2-4x Every render item is currently unique which means neither Maya nor your GPU is able to reuse geometry. Instancing is how games is able to render millions of objects on-screen at 60 fps, and best we can hope for is thousands.
Instancing for Simulation 2-4x Likewise, every physics object is unique and, again, instancing in simulation is how games is able to run destruction and have thousands of objects interact in real-time.

The challenge in both of these is deduplication; of identifying which of the many shapes you use can reuse their geometry.


Overlap Group

Specify which markers may overlap rather than collide. This can be useful to enable dense areas of a character, like the clavicles, where there is natural overlap amongst large shapes like with the neck and spine.

Value Meaning
-1 No overlap allowed
0 Default, respects self-collision on the group (if any)
1-255 Overlap everything with the same number

An rdMarker part of a rdGroup can get an overlap group assigned procedurally, based on other members of that group. For example, in a complete ragdoll, all markers are part of the same group. So a Self Collide = On means these will all be given the same overlap group.

If it isn't in a group, then 0 is the same as -1, in that it will collide with everything.

Let's have a look at a few scenarios.


Collide with Everything

In this example, every marker is part of the same group. The group has Self Collide = Off, which is fine for just about every marker except the fingers. In that case, we do want self-collision, so they are given the group -1.


Respect Self Collision

In this case, we're happy with a default group of 0 since we don't need anything to self collide. Especially these clavicles that overlap significantly!


Surgical Control

Finally, for the very specific cases of wanting two or more markers to overlap. Notice how we give both the ground and 3 of the boxes an Overlap Group = 5.


Asleep

Sometimes, you want things to stay put until something comes into contact with it. That's when you can tell a marker to start asleep, and "wake up" when necessary.


Ignore Gravity

It surrounds us. It penetrates us. It binds the galaxy together. But sometimes, you just don't care.


Quality of Life

A few things to make your day that much more bright. 🌞


Guide Space 2.0

In the previous release, we introduced Guide Space. Which was a quick way of controlling whether a simulation should follow your animation in..

  1. Local Space
  2. World Space
  3. Both

But it was challenging to control, not very obvious. Especially with how it was also taking into account its "group" guide space. This release addresses this by enabling you to specify a guide space for all markers and selectively override only the ones you're interested in. Just like how the Input Space works.

Group Guide Space

Override all guide spaces, by editing the group.

Marker Guide Space

Or gain surgical control over guide space per-marker.

Have Fun

🤭


Auto Delete

The Delete All Physics menu command does what it says on the tin; it deletes all Ragdoll nodes from your Maya scene. But deleting a node, such as the new rSolver left behind anything associated with it, like rGroup and any rMarker nodes.

This releases addresses this by automatically removing anything that depends on the node you delete. For example..

  • Deleting a rMarker node also deletes any associated lollipop controls
  • Deleting a rGroup also deletes the associated rMarker nodes
  • Deleting the rSolver deletes all rGroup and rMarker nodes

Therefore, deleting a solver is now equivalent to Delete All Physics, making it much more intuitive to delete things on a whim.


Reset Button

Minor cosmetic improvement, the Reset to Default button now has an icon so you can actually tell it's a reset button (and not a bug, as many have pointed out 😅).


Z-up

The default plane and solver offset was a off in the previous release, this fixes that. You can also manually re-adjust the plane and remove and orientation from the solver node to fix it locally, the solver itself is A-OK.


Auto Time

Rather than having to specify which frame to start simulating at, Ragdoll can now keep track of your animation start frame. Either the start of the range, or the full timeline. Or, you can still set a Custom start time for when you do care about specifics.

image


Limitations

Monitoring for and responding to changes is a hard problem.

Odds are some things aren't updating the way you expect, which could affect viewport rendering, or worse, the actual simulation. If you encounter any such issues, please let us know in the chat or ping me directly at marcus@ragdolldynamics.com

Here are the currently known issues that we'll be fixing once a solution presents itself.


Motion Blur

As an unintended consequence of the optimisation and shader work, we're currently compliant with Maya's requirement for motion blur. Since all of our simulation is transform-based, it means all of what you simulate can be motion blurred, as opposed to deformer and particle-based motion.

It won't work with any animated attributes, which makes it rather limited in what you can use it for. 🤔


Maintain Offset IK/FK

If you retarget a marker, the difference between the original and target is stored.

When you record, you have the option to Maintain Offset. That's important if the assigned control has a different position and/or orientation than the destination control. For example, you can assign to a joint, but record onto a NURBS control.

For example, IK joints are assigned markers but are retargeted onto FK controls, it's important that you retarget when they are both in a similar pose. Otherwise, the difference between them will remain after recording.

To combat this, you have two options.

  1. Do not maintain offset
  2. Make sure IK and FK match when you Retarget

(1) may not always be an option. If the position and/or orientation of an assigned control is simply different, then there isn't much you can do. :(

(2) is your best option. If you make a mistake, you can always re-retarget to the same control again, and the offset will be updated.


Recording Kinematic Markers

When a marker treats the input as Kinematic, it means it won't simulate it. It'll be 100% locked to animation. If that's the case, then there's really no point in recording those keys, right? Because they'd be 100% identical to the animation?

Except! If there's a parent, then we'll still need those keys to compensate for the parent not being kinematic.

Problem

Let's record without kinematic keys. Notice how the hand isn't given any keys, even though it needed them?

Solution

Record all keys, and the hand - even though kinematic - will still get recorded.


Record to Custom Attributes

Sometimes, rotation isn't coming from Rotate X but rather a custom Ball Roll attribute on a different IK control.

As Ragdoll only understands Translate and Rotate, how would you go about recording onto this attribute!? Here's what you can do.

  1. Create a new Locator
  2. Retarget the foot to this Locator
  3. Connect Locator.rotateX -> R_foot_CTL.ballRoll

Now Ragdoll will record onto a familiar channel, and Maya will handle the conversion back onto the rig.


Slow Constraints

Like in earlier versions, drawing constraints are the slowest part. If you don't need them, disable them. You can do that either on the rSolver node, or individually per rMarker node.


Resources

Some well-hidden but essential resources for any of the above. If you are into anything related to Maya plug-in development and performance, you'll treasure these as I have.