-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Add compute texture demo #938
Conversation
3ccd734
to
1f20cbc
Compare
1f20cbc
to
b720b33
Compare
b720b33
to
0a0351e
Compare
Most times that I run the demo the simulation breaks due to the texture data being full of NaNs, I think the textures should be cleared at the start. |
0a0351e
to
f29a12d
Compare
Hmm, my graphics card driver must do that automatically. Easy fix though, try it again :) |
Consider using this as demo for godot 4 Compute Shader #Source Code:currently 80% works with Godot_v4.0-beta2_win64 |
@GeorgeS2019 That shows a different use case of compute shaders than what we're showcasing here, definately worth having a demo like that here. That should be a question asked to the author of that demo, whether he'd like to add a PR here to submit (a version of) his project. It would be rude to just add it. |
Already asked 😉 |
Hi! I am the author of that Godot project. I have no problem with this being added to the list of official demo projects 😄 I think it needs some work though, will definitely look into how it can qualify as a demo project here. I remember that for this project I had struggles with the lack of multi-pass post processing in the engine. I suppose this has not been implemented yet according to godotengine/godot-proposals#496 |
@BastiaanOlij I quickly ported your code 1:1 to C# any interest adding this to the demo as well? Thx a lot btw for implementing this this opens so many doors now for high-performance apps in Godot Much Love <3 |
Thanks for your contribution. We are getting many users from Unity3D, contributing Godot4 c# DEMO is ONE significant way to welcome them. Thanks again |
@henriksod cheers, I'll find some time to put a PR up. Watching your video I definately had some ideas for improvements so I might see what I can do, no promises :) We are looking into adding something for post processing, but there is still a lot of debate on the direction that will take. |
The policy for C# demos is to avoid having C# ports of demos unless the scripting part is what they are demonstrating. This is because maintaining separate C# demos is a lot of work, so we try to keep the maintenance effort for them minimal. |
btw @Calinou I'm happy for us to merge this as is, I'll revisit this when #79696 gets merged, that isn't a showstopping issue. |
Could you look into revisiting this PR accordingly? I can merge this afterwards. |
@Calinou will do! |
27b4e76
to
e92a039
Compare
Ok, I've added the multi-threaded protection code made possible by #79696 , and enabled multi-threading. It works nicely. I did find one issue with assigning the There is a sync issue left to solve here as we may not do our swap in our rendering thread before we run our process code but in worse case it runs a frame behind. |
e92a039
to
a3cfa4c
Compare
Ok, I've solved the round robin issue, the only issue left now is that in multi-threaded mode, the very first frame our textures haven't been created yet. We can create the texture objects from the main thread, and then do the rest of the work in the render thread, but it may send the wrong message to people looking at the code. |
a3cfa4c
to
90da197
Compare
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.
Tested on 4.2.dev4, it works as expected. I'd wait until 4.2.stable is released to merge though.
There is a small visual issue though: the water's reflection appears to rotate incorrectly when you rotate the camera in the 3D editor viewport.
Also, please move the compute/texture/
folder to misc/compute_texture/
, as it doesn't belong at the top-level. We try to keep the number of top-level folders to a minimum.
PS: We'll need to fix godotengine/godot#75659, as this project triggers it since it needs Multi-Threaded rendering model to work 🙂
I just spent several hours painfully working out how to actual use textures with godot compute shaders... I wish I'd seen this PR! One note-- it might help for there to be two demos, one that's simpler and one that's more complex, to help with the fundamentals without cluttering it with logic that's not 100% related just to using textures with compute-- maybe something as simple as a black screen that brightens, by adding onto the color of the previous frame each frame, using imageStore rather than just making it a fragment shader or sum to help teach how to do random writes, or maybe even just a shader that writes the uv texture onto an input image (this is based on the things I has to figure out manually so I could actually use the shaders in the way I want to...) |
@Calinou the reason I created the compute folder is that I want to make a number of different examples that all use compute shaders. People will be looking specifically for these types of examples so I wonder if |
@Oman395 definately planning on doing more examples :) |
90da197
to
a1e2ac1
Compare
Figured out the dumb mistake I made in the normal calculation, logic I was using was the calculation you normally use in a vertex shader. So just adjusted this to work by mimicking a normal map. |
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.
Should be good to merge after applying suggestions.
# Even though we're using 3 sets, they are identical, so we're kinda cheating | ||
return rd.uniform_set_create([uniform], shader, 0) | ||
|
||
func _initialize_compute_code(p_texture_size): |
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.
func _initialize_compute_code(p_texture_size): | |
func _initialize_compute_code(texture_size): |
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.
I'll change these if that is the style we're now going for, but I personally dislike parameters that look like normal variables, there is a higher chance of making mistakes or accidentally overriding member variables and introducing bugs.
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.
And indeed, this turns out to be the case for nearly every parameter. I'll see what I can do..
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.
Ok, in this case I renamed it to init_with_texture_size
, bit lengthy but now it no longer clashes with the member variable.
It's a little paranoid but the reason this parameter shadows the member variable is because this code is designed on a different thread. It's possible that once the code runs on the render thread, the underlying member is changed on the main thread.
It's not really designed to work that way, we would need to do more if someone changes the texture size after the node is added to the tree, but it is good practice to be consistent in not simply accessing member variables in threads.
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.
I personally agree with using p_
though the general GDScript style omits them
# Now create our uniform set so we can use these textures in our shader | ||
texture_set[i] = _create_uniform_set(texture_rd[i]) | ||
|
||
func _render_process(p_next_texture, p_add_wave_point, p_texture_size, p_damp): |
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.
func _render_process(p_next_texture, p_add_wave_point, p_texture_size, p_damp): | |
func _render_process(next_texture, add_wave_point, texture_size, damp): |
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.
Similar as the discussion above, I've had to get a little creative with renaming these parameters because some shadow member variables. In this case the argument I made up above fully stands. next_texture
,add_wave_point
and damp
can change in the main thread in preparation for the next frame being rendered, while the execution of _render_process
in the render thread works with the data of the previous frame, hence we pass these as parameters.
0d46fe9
to
5d19534
Compare
@AThousandShips I think I got all your changes :) I've left two items unresolved even though I've fixed things up because it is important to capture the feedback. There might be more here we want to document or capture in some way as it is easy for users to ask the question, "why are these parameters, why aren't we using the member variables directly?". It's a logical question to come forward if we don't prefix parameters and thus increase the risk of variables shadowing members which can lead to confusing code. This lies at the heart of why I always prefix my parameters with Multithreading and what changes from frame to frame and how you can break things if you don't think this through are important especially in examples such as these. Simple mutex protection wouldn't help you in this scenario. |
Will take a new look! |
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.
Style looks good!
5d19534
to
e770ce6
Compare
This PR adds a demo that shows off using a compute shader to populate a texture.
Note this requires godotengine/godot#79288 and godotengine/godot#79696, both are merged into master.