How to safely remove node from the scene? #1273
-
Hi, I need to remove a node from the scene.
Now I need to remove node1
Then the rendering got stuck.
What should I do correctly? |
Beta Was this translation helpful? Give feedback.
Replies: 4 comments
-
Hi? I presume real people don't call you w-7v. Could you sign with a human name, this makes it easier for us to track who's who and makes things friendlier. There are several things wrong with your approach so several things you need to learn a bit more about. I think it would be most helpful for you to take a step back and tell us what you are trying to do with your application from a high level, as how best to achieve that will vary from usage case to usage case - trying to help you fix things that are still taking you in the wrong direction isn't going to help you long term, it will just confuse things. |
Beta Was this translation helpful? Give feedback.
-
I'm very sorry that my name.I reset it. I have several models loaded into my program and I am now trying to remove one of them from display and free the associated memory. |
Beta Was this translation helpful? Give feedback.
-
Hi Jacky, The pseudo code you posted suggests you've wrapped the vsg::Viewer, or that your code segment is just written up loosely from memory and doesn't match the original code - I say this because vsg::Viewer doesn't have a render() method so this leaves us wondering what is going on behind the scenes. The second observation is that you are calling viewer.compile() in your rendering loop, this is a bad practice. None of the examples use this approach, they only ever call viewer.compile() prior to running the main loop. I would encourage you to follow the examples as a guide on how to lay things out. If you wish to do compilation of new scene graphs added during the running of the application you should use vsg::CompileManager. See the vsgdynamicload example to see how this is done - this example also manages it multi-threaded. Your rendering loop doesn't have any means of exiting. All the vsgExamples use viewer->advanceToNextFrame() as the start of the rendering loop, this not only does the viewer/graphics thread scheduling but also return false if an exit has been signalled so the loop can exit gracefully. If you don't actually need to remove a subgraph completely, just make it disappear from rendering for a period, then the vsg::Switch node is the appropriate tool to use - just decorate the subgraph with a switch node. Finally, if you actually do need to removing children from the scene graph this should be done in the main rendering loop during the update phase - basically any time between the viewer->advanceToNextFrame() and the viewer->recordAndSubmit() method calls. The group->children is an std::vector<> so calling erase or clear() or whatever you want to perfect sensible usage - I've left the children vector in the public scope so you are free to use all the standard sd::vector<> functionality. Now there is one problem lurking with just going ahead and removing a child, if that subgraph no longer has any references to it, the subgraph will be deleted and all the Vulkan data associated with it will be released as well. If that subgraph has Vulkan elements that are still being rendered on the GPU then you can end up with errors, potentially even a crash. This can happen because Vulkan/GPUs are designed to run concurrently with CPUs, you can put blocks to like waitForCompletion to make sure the CPU waits for the GPU to complete it's work, then it would be safe to remove, while safe and possibly fine for adhoc removal in an interactive rather than a real-time graphics application it's not efficient. The most efficient way of handling this case of preventing deletion of Vulkan resources while they are still being used on the GPU is to take a reference to the subgraph and cache it prior to the subgraph from the group. You then retain the subgraph in this temporary cache for long enough that all the rendering is complete. If triple buffering is being used then keeping a subgraph around for 3 frames before deletion is appropriate. The VSG doesn't yet have an off the shelf cache for this purpose, but it's something I've been working on as part of other work which will be in the up coming 1.1.8 developer release. Until then you'll need to roll your own, it's not complicated just have three std::list<vsg::ref_ptrvsg::Object>> work as the cache for each frame's cache then on each frame clear the cache for 3 frames ago. The functionality I have been working is a refactor how data is transferred during compilation, moving over to using the vsg::TransferTask for this work rather than doing it within the CompileTraversal/Context classes. This work is in the Compile_Using_TransferData branch. The class that will cache the objects for deletion is the vsg::DeleteQueue. The new vsg::DeleteQueue is only used by the DatabasePager right now but my plan is to move it into the vsg::Viewer so you can schedule subgraphs for deletion and not worry about when they are deleted. What will happen is a background thread will delete the subgraphs that are now old enough to be safe to delete, application users will just need to do something like: viewer->deleteQueue->add(subgraph); // schedule subgraph for safe deletion You will still need to remove the subgraphs from your groups etc, as the deleteQueue won't do this for you as it doesn't know how to. Thanks to the safety afforded by the VSG's thread safe ref counting even if you did schedule a subgraph for deletion and it's still in the main scene graph or has any other reference it won't be deleted. I am aiming to get the Compile_Using_TransferData branch completed and merged with VSG master a new dev release out this week. |
Beta Was this translation helpful? Give feedback.
-
Thank you very much for your answer, it is very detailed. Actually my vsg::Viewer is vsgQt::Viewer, I made a mistake about this. For viewer.compile(), I have seen this method used in other people's discussions. I will refer to vsgdynamicload to replace the current method. I am still learning about vulkan and VSG. For this error, I think it should be that the resources are still in use by the GPU. I will try to synchronize the resources of the CPU and GPU. I am very happy to hear that VSG will be updated soon, wish you all the best with your work! |
Beta Was this translation helpful? Give feedback.
Hi Jacky,
The pseudo code you posted suggests you've wrapped the vsg::Viewer, or that your code segment is just written up loosely from memory and doesn't match the original code - I say this because vsg::Viewer doesn't have a render() method so this leaves us wondering what is going on behind the scenes.
The second observation is that you are calling viewer.compile() in your rendering loop, this is a bad practice. None of the examples use this approach, they only ever call viewer.compile() prior to running the main loop. I would encourage you to follow the examples as a guide on how to lay things out.
If you wish to do compilation of new scene graphs added during the running of the appli…