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

Ancestral unloaded payload discovery code results in overly broad resync notices #2286

Closed
nvmkuruc opened this issue Feb 16, 2023 · 5 comments

Comments

@nvmkuruc
Copy link
Collaborator

nvmkuruc commented Feb 16, 2023

Description of Issue

UsdStage::LoadAndUnload takes a set of paths to load and unload on the stage and then expands it to honor the contract of loading ancestral payloads (and properly handle instancing).

In trying to identify ancestral payloads, it uses the following check--

prim && prim.IsLoaded() && p != curPath

However, for active prims without any ancestral payloads prim.IsLoaded() trivially returns true. Therefore, for a payloaded prim without any ancestral payloads, this discovery path will always return that prim's immediate parent. In practice, this means for the simple case of a grouping scope containing a dozen or so payloaded assets, loading one triggers a resync on the parent (implying the siblings and their descendants should be resynced).

To generate resync notices with a better scoped granularity, this code should be updated to either return all ancestral prims with payload composition arcs that are not loaded or the most ancestral prim with a payload that is unloaded.

Steps to Reproduce

  1. Create the following ascii layer
#usda 1.0

over Scope "prim1" {
}

def Scope "root" {
    def Scope "subroot" {
        def "prim1" (payload = </prim1>){}
    }
}
  1. usdview --norender --unloaded <LAYER>.usda
  2. Enable USD_CHANGES and USD_PAYLOAD debug flags
  3. Select /root/subroot/prim1
  4. Load
  5. The terminal reports /root/subroot as requiring a resync when /root/subroot/prim1 would be expected.

System Information (OS, Hardware)

Ubuntu 22.04

Package Versions

Python 3.10
Boost 1.78
TBB 2020.3

Build Flags

--usd-imaging --usdview

@tallytalwar
Copy link
Contributor

Filed as internal issue #USD-8023

@gitamohr
Copy link
Contributor

Nice catch, thanks @nvmkuruc ! I think this is a logic bug in that code. It wants to find the most ancestral unloaded path (i.e. walking unloaded parents, stopping when it finds a loaded parent) but it conflates the check for redundantly reinserting the path p with the stop condition. That is, this bit:

UsdPrim prim = GetPrimAtPath(parentPath);
if (prim && prim.IsLoaded() && p != curPath) {
    finalLoadSet.insert(curPath);
    break;
}

Should instead be:

UsdPrim prim = GetPrimAtPath(parentPath);
if (prim && prim.IsLoaded()) {
    if (p != curPath) {
        finalLoadSet.insert(curPath);
    }
    break;
}

That is, we always stop the search when we find a loaded ancestor and we just don't redundantly reinsert curPath if it's the same as p. This passes your test, which I've added to the suite. I've also added more code comments explaining what's going on here.

Please let me know if this makes sense to you or if I've missed something.

@nvmkuruc
Copy link
Collaborator Author

I think your proposed solution works.

Seeing both your and my proposed solution, I wonder if the conditional exist outside of the loop. So the logic is "Do you have an unloaded parent? If so, find the load / unload boundary." Rather than have that be embedded in the loop.

Happy to have it fixed either way.

@nvmkuruc
Copy link
Collaborator Author

nvmkuruc commented Mar 7, 2024

@jesschimein
Copy link
Collaborator

Thanks for flagging, Matt!

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

4 participants