Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Variant sets on the specialized prims aren’t being expanded properly #3244

Open
tymonpitts opened this issue Aug 21, 2024 · 5 comments
Open

Comments

@tymonpitts
Copy link

Description of Issue

When Specializing a prim from within a Variant, other Variants on the Specialized prim itself are being ignored.

Originally reported here: https://forum.aousd.org/t/quirk-with-variants-specializes/1787

Steps to Reproduce

Given the following layer:

#usda 1.0
class "_class_"
{
    class "asset"
    {
        class "representations"
        {
            class "modelHero" (
                variants = {
                    string lookdev = "v2"
                }
                prepend variantSets = "lookdev"
            )
            {
                def "geo"
                {
                    def "foo"
                    {
                    }
                }
                variantSet "lookdev" = {
                    "v2" {
                        def "mtl"
                        {
                            def Material "myMaterial"
                            {
                            }
                        }

                    }
                }
            }
        }
    }
}

def Xform "element" (
    variants = {
        string mode = "foo"
    }
    prepend variantSets = "mode"
)
{
    variantSet "mode" = {
        "foo" (
            prepend specializes = </_class_/asset/representations/modelHero>
        ) {

        }
    }
}

In the composed stage, the modelHero prim has the mtl/myMaterial prim as expected but the element prim does not.

Other observations of note:

  • Using Inherits instead of Specializes gives the expected result
  • Adding an indirection between element and modelHero by specializing a different prim which then specializes modelHero gives the expected result
  • Specializing the representations parent prim rather than modelHero gives the expected result, albeit with an extra representations prim underneath the element

System Information (OS, Hardware)

Ubuntu 22.04

Package Versions

USD-23.08

Build Flags

@jesschimein
Copy link

Filed as internal issue #USD-10010

@tymonpitts
Copy link
Author

I've run into another example of what I believe is this same bug but the observed behaviour is slightly different. In the original example the contents of the variant are lost while content from other specs are present. In the following example, the contents of the variant are present but the content of a specializing prim are lost:

#usda 1.0

def "Tree"
{
    class "representations"
    {
        def "modelHero"
        {
            def "geo"
            {
                over "leaves"
                {
                    def "Prototypes" (
                        prepend specializes = </Foliage/render>
                    )
                    {
                    }
                }
            }
        }
    }

    def "render" (
        prepend specializes = </Tree/representations/modelHero>
    )
    {
    }
}

def "Foliage" (
    prepend references = </FoliageImpl>
)
{
}

class "FoliageImpl"
{
    class "representations"
    {
        def "modelHero" (
            variants = {
                string testVariantSet = "testVariant"
            }
            prepend variantSets = "testVariantSet"
        )
        {
            variantSet "testVariantSet" = {
                "testVariant" (
                    customData = {
                        string testVariantMetadata = "variantValue"
                    }
                )
                {
                    uniform string testVariantAttr = "variantValue"

                    def "testVariantChild"
                    {
                    }
                }
            }
        }
    }

    def "render" (
        customData = {
            string testRenderPrimMetadata = "renderPrimValue"
        }
        prepend specializes = </FoliageImpl/representations/modelHero>
    )
    {
        uniform string testRenderPrimAttr = "renderPrimValue"

        def "testRenderPrimChild"
        {
        }
    }
}

In the composed stage I'm expecting /Tree/render/geo/leaves/Prototypes to have:

  • testRenderPrimChild child prim
  • testVariantChild child prim
  • testRenderPrimAttr attribute set to "renderPrimValue"
  • testVariantAttr attribute set to "variantValue"
  • testRenderPrimMetadata entry in the customData set to "renderPrimValue"
  • testVariantMetadata entry in the customData set to "variantValue"

However what I see is only:

  • testVariantChild child prim
  • testVariantAttr attribute set to "variantValue"
  • testVariantMetadata entry in the customData set to "variantValue"

All data authored on /FoliageImpl/render is lost on /Tree/render/geo/leaves/Prototypes but is present on /Tree/representations/modelHero/geo/leaves/Prototypes which /Tree/render/geo/leaves/Prototypes is specializing.

I did try to simplify this repro case even more but interestingly if you change almost anything about the composition structure then it starts working as expected. For example, flattening either the Foliage -> FoliageImpl reference arc or the /FoliageImpl/render -> /FoliageImpl/representations/modelHero specialization then the scene composes as expected.

@tymonpitts
Copy link
Author

And here's a variation of the original example with slightly different composition structure:

#usda 1.0
class "_class_asset"
{
    class "representations"
    {
        def "modelHero" (
            prepend specializes = </_class_defaultVariantSelections>
            prepend variantSets = "geometryMode"
        )
        {
            variantSet "geometryMode" = {
                "usd" {
                    def "geo"
                    {
                    }

                }
            }
        }
    }

    def "render" (
        prepend specializes = </_class_asset/representations/modelHero>
    )
    {
    }
}

class "_class_defaultVariantSelections" (
    prepend variantSets = "geometryMode"
    variants = {
        string geometryMode = "usd"
    }
)
{
    variantSet "geometryMode" = {
        "usd" {

        }
    }
}

def Xform "Element" (
    prepend specializes = </_class_asset>
)
{
}

In this case I'm expecting /Element/render/geo to exist but it does not. If you do the variant selection directly on /_class_asset/representations/modelHero it still doesn't work but if you also remove the /_class_defaultVariantSelections class completely then it works as expected. You can also Inherit or Reference /_class_defaultVariantSelections rather than Specialize and it works as expected.

@tymonpitts
Copy link
Author

These are all simplified examples of issues we've run into in production use cases. Thankfully we've discovered these cases before widespread rollout of our planned switch from Inherits to Specializes in some use cases. Due to this bug we are re-evaluating our options (Inherits has issues for our workflows as well which prompted the switch).

Do you have an ETA on when this issue will be looked into? Currently Specializes is very unstable but we might risk using it in a select few cases where it doesn't currently present with this bug. Having a rough estimate on a timeline for a fix will help us make that decision.

@spiffmon
Copy link
Member

Hi @tymonpitts , what I can share right now is that it is a project we anticipate starting when the work to deboostify our python wrappings completes, which will likely be early next year. The project to rework specializes will not be trivial, and has not been bid yet. So, we hope summer/fall 2025, but cannot promise it, as production priorities shift.

Thanks for your patience.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants