Reinitialize water_plane compute resources on scene re-entry#1321
Reinitialize water_plane compute resources on scene re-entry#1321adamcodeworks wants to merge 2 commits into
Conversation
The compute resources and Texture2DRD binding were initialized in _ready, which only fires once per node lifetime. After the first _exit_tree (for example when switching scene tabs in the editor, or reloading the scene at runtime), the resources were freed and never recreated, leaving the plane with a blank texture. Moving the setup to _enter_tree restores the resources on every entry. Closes godotengine#1152.
|
Haven't tested this but the fix seems sound. I'm a little surprised by the problem with switching tabs, I guess there was a recent change where we cache the node tree of each tab loaded? Before I'm pretty sure the tree was reconstructed. All in all, this feels like a safe fix to do. |
|
Tested locally on macOS (both Metal and Vulkan), this doesn't appear to fix the issue on 4.7.beta2. Switching scenes back and forth will still cause 9 errors to be printed and the water texture will no longer update in the editor. |
The previous patch moved init from _ready to _enter_tree, but switching scene tabs in the editor still printed 9 errors and left the water texture frozen on macOS 4.7.beta2 (reported by Calinou). Two remaining issues: * The Texture2DRD declared as a SubResource on the material doesn't survive a scene unload reliably. Create a fresh Texture2DRD in _enter_tree and bind it onto the material instead of reading whatever the scene hands back. * _initialize_compute_code is queued onto the render thread, but _process keeps running on the main thread in the meantime. Between re-entry and the render thread completing, _process would bind texture_rds[next_texture] - which still holds the previous lifecycle's now-freed RIDs - to the texture. Add a ready_for_render flag that the render thread sets after init completes; _process bails out until then. Also reset texture_rds/texture_sets/shader/pipeline at the end of _free_compute_resources so nothing stale lingers.
|
Thanks for re-testing @Calinou — pushed a follow-up that should address the 9 errors and the frozen texture on 4.7.beta2. Two extra things on top of the original
PR body updated with the full description. I haven't been able to retest on macOS — could you give it another spin when you have a moment? |
Fixes #1152.
What's wrong
Switching the scene tab away from the water plane and back (or reloading the scene at runtime) left the plane blank and printed errors. Three things were going wrong:
Texture2DRDbinding were set up in_ready, which only fires the first time a node enters the tree._exit_treewas already clearingtexture_rd_ridand freeing the compute resources, but on re-entry nothing rebuilt them.Texture2DRDSubResource doesn't survive an unload reliably. Picking it back up viamaterial.get_shader_parameter(&"effect_texture")on re-entry returned aTexture2DRDwhose underlying RD texture had been torn down._initialize_compute_codeis queued onto the render thread viacall_on_render_thread. Between_enter_treereturning and the render thread actually running,_processkept running on the main thread and boundtexture_rds[next_texture]— still holding the previous lifecycle's now-freed RIDs — onto the texture. With 9 uniform sets backed by those RIDs you get exactly the 9 errors@Calinoureported on 4.7.beta2.Fix
In
water_plane.gd:_readyinto_enter_treeso it runs every tree entry (matches what_exit_treewas already pairing with, and the approach@BastiaanOlijsuggested in the issue).Texture2DRDin_enter_treeand bind it onto the material withset_shader_parameter, instead of reading whatever the scene hands back. The script owns theTexture2DRD's lifetime now, so reloads can't leave it stranded.ready_for_renderflag set on the render thread at the end of_initialize_compute_codeand cleared on the main thread in_exit_tree._processbails out before binding/dispatching while it's false, so we no longer bind freed RIDs during the init window.texture_rds/texture_sets/shader/pipelineat the end of_free_compute_resourcesso a stale read from the main thread can never observe freed RIDs.No changes to the GLSL,
.tscn, or any other file.Verification
I wrote a small standalone scene mirroring the lifecycle pattern (init in
_readyvs. init in_enter_tree) and exercised it throughadd_child/remove_child:I haven't loaded the patched scene in the editor to confirm the 9 errors are gone and the ripples come back visually after a tab switch on macOS — please re-test before merging.