I am working on a render delegate, where I first noticed this issue. But then also saw that it happens in Storm/USDVIEW (tried in different versions, including 0.24.05)
Consider this scenario :
The USD render purposes, when loaded, seem to linger if toggled off. For example consider this scenario, in USDVIEW :
A scene with vertex animation, there is a proxy mesh and a heavy render mesh.
Loaded in USD view, initially only the proxy mesh is displayed → High FPS.
Turn OFF the proxy purpose + Turn ON render purpose → lower FPS / higher memory usage, as expected.
But now… toggle back to proxies → Still low FPS
In my delegate, I see that the mesh ::Sync() is still called for the render mesh even if the render purpose is not wanted, with the obvious performance implications.
I found several issues that seem related :
A seemingly relevant quote :
Note that the design of purpose in hydra is to:
(1) Create a prim the first time its purpose is included in a draw call.
(2) Only update prims (via Sync) when their purpose is included in a draw call.
(3) Never delete prims based on purpose.
→ This is not what I am seeing, I am still getting the Sync() call in my render delegate even if the purpose if off. And I guess it is the same in storm, as the performance does not get back to normal when toggling “render” off.
Is there a bug here?
Another interesting one :
I got our delegate to work but it is rather kludgy. It looks like Sync() is only called on rprims that should now be visible when the set changes, so I had that turn on any that are turned off. And RenderPass also tracks the RenderTags being passed to it, and if any tags are removed it goes through all the rprims and turns off (using a delegate-specific api) any that have that removed purpose. There is no need for RenderPass to turn anything on, Hydra is at least partially doing the right thing.
I recommend that Hydra destroy the rprims with the wrong purpose, as this would return the index to the same state it would be if created initially with that purpose set.
Further tests show that the new RenderTags are not sent to RenderPass until after Sync() is called on all the prims, so checking against them is useless. I will have to rely on the fact that Sync() is only called on objects that should be visible. This is going to limit what patches can be done, it does look like calling Finalize (and probably destroying) the unwanted prims is the only solution that will continue to work with code that works with the current version.
I am not entirely clear on everything mentionned here, but it sounds like perhaps there is indeed an issue, and hydra should be doing more, but that some solution can be done at the delegate level - right now I have some hack that exits the Sync() early if the purpose of the prim is not in use. But this sounds a bit better, although am not sure exactly how that would work - could someone expand a bit on this, is there code I could look at? I had tried to manually remove the rprims from the delegate when the purpose is toggled off, but that led to other issues, where when toggling back on the purpose, they would not get re-added properly…