Batched export and merge to USD#4279
Conversation
lib/mayaUsd/fileio/jobs/writeJob.cpp
Outdated
| static double _GetMetersPerUnitFallback() { return UsdGeomLinearUnits::centimeters; } | ||
|
|
||
| /// Converts Maya units to metersPerUnit values used in USD metadata. | ||
| static double _ConvertMayaUnitToMetersPerUnit(MDistance::Unit mayaUnit) |
There was a problem hiding this comment.
There was already UsdMayaUtil::ConvertMDistanceUnitToUsdGeomLinearUnit(), but that does raise a coding error when the units are not found. We could remove the coding error if that is why you did not use it.
There was a problem hiding this comment.
Thank you for pointing out UsdMayaUtil::ConvertMDistanceUnitToUsdGeomLinearUnit(). I’ve replaced my local impl, I simply missed the existing one. c733a53
The coding error seems appropriate here: we only call it with the values returned by MDistance::uiUnit() and MDistance::internalUnit(), I believe an error would surface only if a valid enum value is not handled yet by the function.
pierrebai-adsk
left a comment
There was a problem hiding this comment.
Needs a few fixes, but otherwise great work.
|
Thank you for the review @pierrebai-adsk |
a537f29 to
c733a53
Compare
|
I’ve addressed the requested changes and fixes. |
c733a53 to
3b8e5ab
Compare
|
The test testCacheToUsd failed: Something changed that makes the payload have backslashes instead of forward slashes. I don't know if you can easily identify what could have affected this in your changes? I might take a look this afternoon, but you might have an idea. |
Yes, I think I know why. In |
I looked at it more closely. It seems payloads had backslashes on Windows even before these changes. What changed is that the regex only matched one component of the asset path, so the slash style didn’t matter. I would propose to change the test to assert on the actual @@ -317,7 +317,7 @@ class CacheToUsdTestCase(unittest.TestCase):
if relativePath:
if self.stage.GetRootLayer().anonymous:
self.assertNotIn('payload = @testCacheToUsd/cache.usda', self.stage.GetRootLayer().ExportToString())
- self.assertRegexpMatches(self.stage.GetRootLayer().ExportToString(), 'payload = @.*testCacheToUsd/cache.usda')
+ self.assertIn('payload = @' + cacheFile, self.stage.GetRootLayer().ExportToString())
self.makeRootLayerNotAnonymous()
mayaUsd.lib.Util.updatePostponedRelativePaths(self.stage.GetRootLayer())This passes on linux but I dont have a windows box available. |
|
@pierrebai-adsk It looks like the CI failed due to a timeout, it isn’t a code error? I took the opportunity to push two last-minute commits: |
|
We will do some QA on it internally before approving |
Extracted USD stage metadata authoring from AutoUpAxisAndUnitsChanger to UsdMaya_WriteJob::_Finalize. AutoUpAxisAndUnitsChanger now only temporarily tweaks Maya scene within the scope of _Write, it is not related anymore to a stage. This change is needed for following changes to allow batching multiple writeJobs, writing to multiple stages, in a single maya timeline run.
So that the maya scene tweaks needed for the export time are done and restored at the Write method scope. This change is needed for following changes to allow batching multiple writeJobs, writing to multiple stages, in a single maya timeline run.
- _PostWrite that might fail. - _FinishWriting is now assumed to always succeed.
This message does not seem useful with maya-usd coalesced diagnostics and its removal simplifies upcoming changes enabling jobs batching.
…ovided at construction. This simplifies upcoming changes enabling jobs batching.
…f jobs.
UsdMaya_WriteJobBatch:
The public API to queue multiple independent UsdMaya_WriteJobs, each
writing to a different output stage. It optimizes the export of multiple
USD stages from an animated Maya scene by reducing redundant evaluations
to a single timeline pass.
UsdMaya_WriteJobImpl:
Implements the writing logic shared by UsdMaya_WriteJob::Write() and
UsdMaya_WriteJobBatch::Write():
- Applies the temporary Maya scene tweaks needed for the export.
- Calls `_BeginWriting`, `_PostExport`, `_FinishWriting` for each job.
- Builds a sorted union of all jobs’ `timeSamples`, then for every
frame in that union:
- Advances Maya to the frame.
- Advances each job’s sample iterator and writes or skips the frame
as appropriate.
This keeps per-job code focused on writing USD data while ensuring we
it does not over-evaluate the Maya animation.
- Add class PushToUsdArgs, the arguments needed for push-like operations: the source and destination objects, UsdMayaPrimUpdaterArgs and userArgs dict. It has convenient factory methods that will mainly apply the userArgs overrides required for the wanted push operation. - Added a mergeToUsd overload which takes a PushToUsdArgs. - pushExport now takes a PushToUsdArgs, it does not need anymore a UsdMayaPrimUpdaterContext. - Updated maya command and python bindings to use the new mergeToUsd overload, and the PushToUsdArgs factory method. - These changes will help to implement a mergeToUsd method than can execute multiple objects merge operations.
… in single call.
- pushExport now takes a vector of PushToUsdArgs, it will export animation
of all push operations in a single timeline pass thanx to
UsdMaya_WriteJobBatch.
- mergeToUsd now takes a vector of PushToUsdArgs. This allows for
multiple merge operations in a single call. It will:
- validate all args and prepare for pushExport in a first phase.
- Call pushExport once.
- pushCustomise and perform other post pushExport process for all
pushed items.
- Did not change the signature of duplicateToUsd to allow batched
duplications, but it could also be added if needed.
… in a single call. It accepts a sequence of tuple: the pulled dagPath name and the userArgs dictionary for each object merge operation.
- testMergeToUsd.testBatchMergeToUsd: Tests basic batch merge functionality, and batch args validation. - testCustomRig.py.testCustomRigUpdaterBatchMergeAnimToUsd: Tests batch merge with a custom updater. Also tests animation evaluation aspects. - testCacheToUsd.testEditAndBatchMergeRigMayaRefs: Tests caching to USD a batch of MayaReference prims.
…le call. The command now accepts multiple string object arguments, instead of a single dagPath. exportOptions flag is now multiUse. If any, there must be the same number of exportOptions as dag objects.
…ergeToUsd, and undoing/redoing.
- Allow callers to pass a single exportOptions string and use it for multiple merge operations. - Fix an issue in mayaUsdMergeToUsd where it did not correctly issue an error (and could crash) when receiving multiple exportOptions whose count did not match the expectations. - Fix coding‑style.
…rUnit instead of local implémentation.
…sing. When a single exportOptions string is given for multiple dags, it is now converted to userArgs dictionary only once.
…ple dag objects. It should accept a single string and as many strings as given objects.
There was a mel command typo in _ActivateRenderLayer.
115f5ee to
7455e55
Compare
|
I’ve just rebased onto dev and resolved a conflict with |
|
@jufrantz Sorry the delay. QA has internally tested the changes and given approval. Pierre is currently away so we are waiting for him to come back to finish the code review. Then we'll get this one merged. |
With this PR
PrimUpdaterManager::mergeToUsdcan now merge multiple pulled DAG paths to separate prims in a single invocation.This is mostly interesting in the context of animated rigs, referenced with
MayaReferenceprims.The feature matches our previous Alembic "cache-and-swap" workflow that used
AbcExportwith multiplejobArgsflags, to export multiple rigs animation to separate files in one go.Why it matters
Constraint‑safe
mergeToUsdremoves the Maya data at end of the operation, swapping it to the USD data. For aMayaRefeferenceprim, the Maya reference gets unloaded.In animation work, rigs are often connected to each others. Characters might be constrained to vehicles, props to characters, characters to characters, etc
Artists (and tools) must therefore cache the rig animations in an appropriate order (driven first then driver) so every constrained rig evaluates with their complete upstream graph, this can become a complex task. If the rig graph contains a cycle, which is possible at the rig-level, caching becomes impossible without another manual pre-baking.
With a "merge batch", all referenced rigs remain loaded until all USD data is authored, so the rigs remain connected to live Maya data during the whole evaluation. Artists can export the whole scene, or a group of related rigs, in one go. Order and cycles stop mattering.
Less waiting
Batching merge operations optimizes
“Cache to USD”for animated rigs. In production, rig animation evaluation is the main cost of this caching. Currently, artists must export each referenced rig one‑by‑one; each export walks the same frame range again, making some rigs recompute identical results.The new batched export walks the timeline once and shares evaluations across all rigs, eliminating this redundancy.
I tested performances with this scene
four_animated_rhinos.maand using this script test_merge_four_animated_rhinos.py. The scene is featuring 4 animated references torhino_rig_001.ma, the rig file was found in maya-usd unit-tests.Details
UsdMaya_WriteJobBatch
New class, a collection of
UsdMaya_WriteJob, that will execute all jobs, each writing to a separate stage, and write the timeSamples in a single unioned Maya timeline pass. jufrantz@aacaf4dUsdMaya_WriteJob
Destination file name and append flag are now supplied in the constructor, instead of the Write method. This is to ease implementation of
UsdMaya_WriteJobBatch. If this is a concern, I could rework this change. jufrantz@5e32d35Internal refactors
UsdMaya_WriteJobandUsdMaya_WriteJobBatchis centralized in a new private classUsdMaya_WriteJobImpl. jufrantz@aacaf4dUsdMaya_WriteJob::_BeginWritingwas adapting the maya scene forrenderLayerMode,upAxis, andunitoptions.UsdMaya_WriteJob, so I refactored those aspects:UsdMaya_WriteJobBatch::WriteJobsand encloses multiple jobs evaluation.UsdMaya_WriteJob.PrimUpdaterManager
PushToUsdArgsstruct that bundles all inputs common to push‑style operations (mergeToUsd,duplicateToUsd). jufrantz@aaa06a7PrimUpdaterManager::mergeToUsdnow takes astd::vector<PushToUsdArgs>, so multiple DAGs can be exported in one call. jufrantz@3f68054Tests
Added unit tests for batched merge, custom rig updaters,
MayaReferencecaching, undo/redo integrity.jufrantz@0bbf955, jufrantz@a537f29
I did not
mayaUsdExportcommand. I imagine this could be added with a flag similar toAbcExport -jobArg/mayaUsdMergeToUsd -exportOptions, but I am unsure of the best syntax.duplicateToUsd; though the same technique would work.I'd be happy to add any of these in a later PR if you think they are useful.
PS
This PR introduces a large set of changes, but I prefered to keep everything in one pull request to give you the full picture. However there are clearly 2 subsets of changes (UsdMaya_WriteJob + PrimUpdaterManager), I could split this PR in two if you prefer.
I've organized the changes into logical commits to make the review easier. Hope that helps.
Feedbacks are very welcome,
Julien