USDUtils.FlattenLayerStack and references with Sdf.LayerOffsets

Hello!
We’ve noticed a little bit of strange behavior with UsdUtils.FlattenLayerStack when dealing with a stage that has references/payloads with LayerOffsets (scaling 24fps to 60fps) and deleted references/payloads. In the following examples, I have a base file at 60fps that references assets in a 24fps sublayer. After running FlattenLayerStack on the root layer, I seem to get a composition that doesn’t match the original.

from pxr import Usd, UsdUtils

original_stage = Usd.Stage.Open("base.usda")
flatten_layer_stage = Usd.Stage.Open(UsdUtils.FlattenLayerStack(original_stage))

print("Original")
for prim in original_stage.Traverse():
    print(prim)
print("FlattenLayerStack")
for prim in flatten_layer_stage.Traverse():
    print(prim)

Results in:

Original
Usd.Prim(</World>)
Usd.Prim(</World/PayloadIn24>)
Usd.Prim(</World/ReferenceIn24>)
FlattenLayerStack
Usd.Prim(</World>)
Usd.Prim(</World/PayloadIn24>)
Usd.Prim(</World/PayloadIn24/asset_child>)
Usd.Prim(</World/ReferenceIn24>)
Usd.Prim(</World/ReferenceIn24/asset_child>)

The result of the FlattenLayerStack produces a Prim with the following :

    def "ReferenceIn24" (
        delete references = @C:\Users\jaker\temp\flattenlayerstack\asset.usda@
        prepend references = @C:\Users\jaker\temp\flattenlayerstack\asset.usda@ (scale = 2.5)
    )
    {
    }

These sublayers and delete/prepends were all added by a DCC so I’m wondering if there is some combination of adding a scale to them that might make the FlattenLayerStack match the original stage? Or, maybe am I misunderstanding the capabilities of FlattenLayerStack?
Thank you!

asset.usda (104 Bytes)
base.usda (422 Bytes)
layer_24.usda (336 Bytes)

Oh my goodness, @Truant , great find that I’m surprised has gone undetected for so long. WOuld you be kind enough to turn this into GitHub bug report? What’s happening is that in the composition engine, we add a dynamically computed LayerOffset to account for the differing timeCodesPerSecond of the source and destination layers. But we’re not recognizing that it’s synthetic in the layer flattening code, and treating it as if it were part of the authored references/payloads statement.

Not sure if we currently have enough breadcrumbs, post-composition, to recognize it, but if not we’ll need to figure out how, since this is obviously incorrect, and I don’t think there is a way to fix it yourself. I think adding the scale in base.usda would cause un-flattened composition to fail.

Thank you Spiff! I will fill out a Github bug report for this issue. It’s a fairly unique edge case so it probably hasn’t popped up much before.