-
-
Notifications
You must be signed in to change notification settings - Fork 260
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
Fix for GPU Generation Hitting Rid Allocation Limit #735
base: master
Are you sure you want to change the base?
Conversation
Thanks for spotting it! Back when I first tested GPU stuff with Godot when they just came out, I started the dev project for making shaders in the module's repo, and freeing uniform sets was commented out. I don't remember why, but I notice that I consistently never freed uniform sets. Forgot the reason as well. |
@@ -151,7 +151,7 @@ void GenerateBlockGPUTask::prepare(GPUTaskContext &ctx) { | |||
// Note, this internally locks RenderingDeviceVulkan's class mutex. Which means it could perhaps be used outside | |||
// of the compute list (which already locks the class mutex until it ends). Thankfully, it uses a recursive | |||
// Mutex (instead of BinaryMutex) | |||
const RID generator_uniform_set = | |||
_generator_uniform_set = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is in a for loop. You will still leak RIDs in different setups.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ahh yeah tunnel vision. I'll have to fix that. I'm surprised the change is making a much of a difference at all given that added context.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Multi-box situations occur in particular cases (notably edited terrain) that you might not have encountered.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That makes sense. The other places using uniform_set_create are in the render_detail_texture_gpu_task which I also wouldn't have seen. So I'll try turning that on and doing some edits in the next pass.
It's funny you mention that because I have another script where I was also trying to free the uniform set because I was following the documentation but it resulted in saying I was freeing something invalid which I wasn't expecting. In this case it's not complaining about anything so I assume it's a valid thing to clear . Point being I'm not really sure what the deal is with uniform sets either. |
I asked devs, and apparently uniform sets are supposed to be "freed by their dependencies" automatically, which hopefully means if one of their contents is freed, then the uniform set is freed. Hence the absence of freeing in the code. This is still unclear to me because none of this is documented... Considering uniform sets are then supposed to be automatically freed... I'm also told the issue could be something else. Note: the PR still lacks a lot of areas to free uniform sets. I wrote the full fix locally (and pushed a branch to Git because I will soon pack my desktop computer and want stuff saved) but not going to apply it just yet, as apparently it needs more investigation about the root cause |
Attached is a minimal reproduction project. All you need to do is play the one scene and wait 2 minutes or so. Things to note. I'm running a pretty much 4.4 double precision build of godot. (I really hope this isn't another random double build specific behavior being weird.) I don't notice anything because of the double precision but if you start seeing the mesh looking strange it might just be because the camera is getting far out. You should see the issues around 21km though so I don't think you'd run into anything super noticeable until you hit the allocation issue and then you'll really notice some weirdness along with the printed errors. Edit: Better minimal test version here. It looks a bit worse but it triggers it a bit faster. Second Edit: |
An aside, I tried out having detail normal maps enabled with the gpu generation on my other project where I ran into this originally after making the for loop update and I didn't seem to hit any issues. Not sure why. Maybe I didn't let it go long enough or those uniform_sets are being cleaned up automatically? Did you try out your branch with detail normal maps and get any double free errors/warnings? |
So far my tests just show that without my branch, moving forwards periodically reaches this line: https://github.com/godotengine/godot/blob/7459a0361d7cea65e190232ae60c6fcc275c73f5/core/templates/rid_owner.h#L127 Something new though: |
The pooling would explain why I didn't see anything with the normal maps assuming those uniform sets aren't part of a pooled resource. See my edits to the comment with my minimal reproduction project if you didn't already. I don't think you'll need the new version if you're just tracking the chunk_count directly though. |
Not exactly. Uniform sets are never pooled. It is the pooling of storage buffers that contributes to make the GPU chunk generation not auto-free uniform sets. Because then Godot sees that all resources referenced by the uniform remain alive so it assumes the uniform set is still in use (but it isnt). |
Right. We're on the same page. I was saying if whatever resource the uniform set belongs to isn't pooled (the textures in this case based on what you're saying) it would explain why I didn't see any problems. And no I didn't include it in the minimal examples mainly because I didn't want to recreate the shader since I didn't see anything in the other project but I probably should've and turned it on just to cover all the bases. Sorry about that if that wasn't clear. |
I was running into an issue where after a couple of minutes of flying around with gpu generation on where I would start hitting the rid allocation limit. I took a look at the code and noticed the generator_uniform_set variable was being created but never cleared as far as I could tell. So I switched it to a member variable like _generator_pipeline_rid and freed it along with that and it seems to fix the problem.
I didn't see any resource allocation issues after ~15 minutes of flying around with this change where as before I was hitting the issue after ~3 minutes.