Dynamic file format behavior changes with 24.03

Hi,

I’m working on the SBSAR plugin for Adobe, which is a dynamic file format plugin. We’re currently in the process of upgrading to USD 24.03 and we noticed a behavior change in our plugin that breaks the workflow that was previously working for us.

This recent change to the PcpDynamicFileFormatContext caused the change in behavior: pcp: Fixes for dynamic payload argument composition · PixarAnimationStudios/OpenUSD@715ccf7 · GitHub

Following the advice we got in the past from Spiff (https://groups.google.com/g/usd-interest/c/mUJ64KpU9cU/m/Hf3n7OQFAwAJ) we are creating two nested variant sets for resolution and preset and inside of that we set up the payload arc that is dynamic.

Before the recent change, the plugin was able to get the default value of attributes set inside of the variants as well as attribute value that are set on the parent prim outside of the variant sets. With the new code we only see the attribute values from within the variant sets, but not from regular attributes set on the prim.

I tried lofting the payload arc to the parent prim and be outside of the variant sets, but that prevents the plugin from seeing the values set within the variant sets. But now regular attributes started working. I suspect we still have the issue that was mentioned in the original usd-interest forum post.

I traced the code that changed in Pcp and see the difference in the resolution behavior. We’re wondering if either a) we were doing something that worked by chance, but is not actually correct or b) the recent change had an unintentional side effect on our scenario.

In either case we could use some advice on how to structure our dynamic payload to work with both attributes set in variants and those directly on a prim.

Thanks,
Florian

Hi Florian! We chatted about this, and from your description, we can’t see how the indicated change would have broken anything.

Could you possibly provide us with a usda file that demonstrates the problem you’re seeing, using one of the example dynamic file formats we ship in pxr/extras?

Thanks!

Thanks for the quick response. I’ll try to create a simplified repro for this. How should I submit it to you? Post here? GitHub issue? Email?

Thanks,
Florian

Posting here would be great if you can, for ease/longevity, but any delivery method will work :slight_smile: Thanks!

…and just to fill you in:

  • We are currently wrapping work on fixing the problem noted in the usd-interest thread that necessitated your workaround
  • The only way we can think of that might cause behavior like you described would involve sub-root payload arcs

I’m still catching up on many of the low level composition bits. What is a “sub-root payload arc”? A payload arc on a prim that is not a root prim? A payload arc that does not point at a root prim, but at something deeper in the hierarchy of the target file?

Corey said: Sunya’s change I would expect to only have affected the behavior for subroot payloads, i.e. reference = </PrimWithDynamicPayload/SomeChild> . I.e., only if you were referencing past the prim that has a dynamic payload.

I’ve been able to work with the Test_PcpDynamicFileFormatPlugin_FileFormat plugin and make a unit test like setup that shows what I think is not working as expected. All the pieces are in the tiny zip file including an additional test case for the existing unit test in Pcp. I’ll post the structure of what we’re doing here as well for ease of reading it.

We create a variant setup around the dynamic payload that looks like this if you squint really hard. There are two nested variant sets and the inner most variant contains a payload to the actual dynamic payload. The variants do set attribute default values that drive the generated content. In this example we only care about TestPcp_height.

#sdf 1.4.32
(
    defaultPrim = "MaterialWithVariants"
)

def Material "MaterialWithVariants" (
    variants = {
        string resolution = "resSmall"
    }
    prepend variantSets = "resolution"
)
{
    int TestPcp_depth = 2
    int TestPcp_num = 2
    # This also works. Commented out see variants in effect
    #double TestPcp_height = 77.0

    variantSet "resolution" = {
        "resSmall" (
            variants = {
                string preset = "__default__"
            }
            prepend variantSets = "preset"
        ) {
            double TestPcp_radius = 50.0
            variantSet "preset" = {
                "PresetA" (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_height = 11.0
                }
                "PresetB" (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_height = 22.0
                }
                "__default__"  (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_height = 33.0
                }
            }

        }
        "resBig" (
            variants = {
                string preset = "__default__"
            }
            prepend variantSets = "preset"
        ) {
            double TestPcp_radius = 100.0
            variantSet "preset" = {
                "PresetA" (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_height = 44.0
                }
                "PresetB" (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_radius = 55.0
                }
                "__default__" (
                    payload = @./material.testpcpdynamic@
                ) {
                    double TestPcp_height = 66.0
                }
            }

        }
    }
}

When we want to use this setup we reference it into a scene and do additional tweaks to the attribute default values to tweak things. This works partially, but not directly on the final prims in the scene as indicated by the comment:

#sdf 1.4.32
(
    subLayers = [@./material_variants.sdf@]
)

over "MaterialWithVariants" {
    # XXX This works!
    double TestPcp_height = 88.0
}

def Material "MaterialWithVariants2" (
    prepend references = @./material_variants.sdf@
)
{
    # XXX This works!
    double TestPcp_height = 99.0
}

def Xform "World"
{
    def Material "MatWithLocalReference" (
        prepend references = </MaterialWithVariants>
        variants = {
            string resolution = "resBig"
            string preset = "PresetA"
        }
    )
    {
        # XXX This does not work! <==================================================
        double TestPcp_height = 110.0
    }

    def Material "MatWithDirectReference" (
        prepend references = @./material_variants.sdf@
        variants = {
            string resolution = "resSmall"
            string preset = "PresetB"
        }
    ) {
        int TestPcp_depth = 2
        int TestPcp_num = 2
        # XXX This does not work! <==================================================
        double TestPcp_height = 120.0
    }

    def Material "MatWithIndirectReference" (
        prepend references = </MaterialWithVariants2>
        variants = {
            string resolution = "resSmall"
            string preset = "PresetA"
        }
    ) {
        int TestPcp_depth = 2
        int TestPcp_num = 2
        # XXX This does not work! <==================================================
        double TestPcp_height = 130.0
    }
}

I hope this helps shed some light on the scenario that we’re creating and that is not working anymore. Thanks so much looking into this.

filesForPcpDynamicFileFormatPlugin.zip (3.0 KB)

For additional context/shameless plug, the sbsar plugin is now open sourced and it suffers from the issue Florian is describing:

Thanks, @fhecht - we’ll get right on this!

1 Like

I did a bit of digging on my own and I think the problem is coming from this piece of code:

For the example above something like this happens:

The original path in this code is “/MaterialWithVariants{resolution=resSmall}{preset=PresetB}”, which is where the payload arc is introduced for the currently selected variant choices.

The code then tries to map it to the root node of the composition graph. The rootNode in this case is “/World/MatWithDirectReference”, but because of the MapToSourceTarget, the pathInRootNode ends up being “/World/MatWithDirectReference{resolution=resSmall}{preset=PresetB}”.

It tries to find the attribute default values there, but fails since that doesn’t exist. It then visits the children in the PcpNode tree, but the first jump to the child skips over the actual composition root (“/World/MatWithDirectReference”).

If I disable this if statement and instead rely on the second code path that maps up the PcpNode hierarchy, I end up with the composition root (“/World/MatWithDirectReference”) and then the rest of the code can find the attribute values as expected.

@spiff please forward this to who ever has the fun job of figuring this one out.

Cheers!

Thanks @fhecht for the sample unit test and digging into the code! The issue was exactly in the code you pointed out and a fix for it (with a test based on one of the cases you provided) will be releasing shortly in the next dev push!

If it’s helpful in the meantime, the fix is just replacing path with curPath here. Let us know if any other issues pop up!

Thanks so much @diyajoy. I’ll give that fix a spin on our side, but I already know it’ll fix it.

This quick checking and fast turn around is very much appreciated. Cheers!