-
-
Notifications
You must be signed in to change notification settings - Fork 98
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 support for Shader Storage Buffer Objects (SSBO) #7516
Comments
Note that SSBOs don't have an equivalent in OpenGL ES 3.0, so any shaders using those will not work when using the Compatibility rendering method.
Uniform arrays are supported since 4.0, though only with a predetermined size: #931 |
Hello, I appreciate you pointing out the existing uniform array functionality added in Godot 4.0. I was unaware of that addition previously, so thank you for bringing it to my attention. As you noted, shader storage buffers do not have an OpenGL ES 3.0 equivalent. I did not realize this initially. As such, any shaders utilizing SSBOs would only be compatible with the Forward+ rendering path in Godot. With that technical context in mind, here is an updated summary of the proposal:
Please provide any additional feedback on improving this proposal while preserving the core intent! I'm open to refining it based on the helpful information you've provided regarding Godot's rendering architecture and capabilities. |
The current state of things right now is that Godot does support SSBO's, but only with the RD renderers and only when using RD rendering commands (i.e. they don't work in GDShaders). That being said, I am wary of adding significant complexity to GDShaders that will be inaccessible to many users. Especially since it is unclear what benefit SSBO's would have in this context. As a reminder, SSBOs function like Uniform Buffers except they are (potentially) slower on some hardware, and have a much larger size limit. You can also write to them from compute shaders just like images, in fact, most GPUs use the same instructions for reading/writing SSBOs as they do for reading/writing images (the performance is the same). In light of the above, it seems like the benefit of SSBOs is that they are a little easier to write to from CPU-side than images (but more cumbersome than uniform arrays), and they don't have the size limit of uniform arrays. To me, that niche benefit doesn't really seem worth adding the complexity. Especially since uniform buffers and images are supported on all hardware and all of our backends. |
Is this related to #6989? |
+1 ideally would be good - I am looking to port my compute shader and frag shaders from Unity and I am reliant on structured buffers, though I did have a hacky version working using textures, I suppose I could use that or I could use lots of structured buffers. |
The main benefit for me is that they are possible to write to from other shaders, making it possible to offload more work to the GPU and share state across stages and passes. In addition to not having the same size limit, they are dynamically sized which allows for more generic shaders.
I use shader buffers all the time and would not consider them niche, but perhaps I'm an outlier. I agree that their overall benefits are less clear when one is not in control of the full rendering pipeline as is the case with Godot, but I still think a simple interface (e.g. as flat buffers of primitives like float rather than structs as in GLSL) to shader buffers can bring a lot to the table. |
Yes, we do need similar functions. The current uniform size limit is quite strict. |
Seems storage buffer (If i recognize it correctly, it is ssbo) is already defined for compute shader and can be add to uniform set just like other uniforms. Maybe the only issue here is define those we need in gdshader. Looks good! |
I'm not gonna lie, but it would be nice to be able to use them in gdshader. |
@lemonJumps I haven't tried these already, but probably it will solve your problem. |
+1 The math for grabbing 8-16 bits in a NxM Texture can get complicated quickly and has caused a lot of headache in my project. In fact, I have not even figured out how I can store 3 floats worth of information in a texture and access those floats. To mitigate this complexity I have had to write unit tests to make sure I am doing the math correctly. Here is a taste of the complexity I am talking about, I do this several times throughout my shader. int i = (VERTEX_ID/4) * FACE_BUFFER_LEN;
ivec2 face_index = ivec2(
(i/4) % FACE_TEX_WIDTH,
(i/4) / FACE_TEX_WIDTH);
float tex_id_quad_id = texelFetch(_faceBuffer, face_index, 0)[(i) % 4];
int texture_buffer_index = int(float(floatBitsToUint(tex_id_quad_id) >> uint(16)));
int quad = int(float(floatBitsToUint(tex_id_quad_id) & uint(0xFFFF))) * QUAD_DATA_SIZE;
int block_buffer_index = int(floatBitsToUint(texelFetch(_faceBuffer, face_index, 0)[(i+1) % 4])); // note, this won't work for i+2 or an odd number of floats
float pos = texelFetch(_blockBuffer, ivec2(block_buffer_index/4, 0), 0)[(block_buffer_index % 4)];
float custom_data = texelFetch(_blockBuffer, ivec2(block_buffer_index/4, 0), 0)[((block_buffer_index + 1) % 4)]; SSBOs or even an array of floats would make such code much more simple and reliable. Unfortunately uniform arrays would not work for my use case unless I want to allocate 256kb of vram per instance of my shader (done that, cost me GiBs of vram). |
+1 on the idea of SSBO implementation, its would allow for greater capabilities of interaction with memory and possible variable length arrays too for universal shader for variable mediums (like point clouds with dozens of attributes to each) |
Describe the project you are working on
I'm working on a 2D game with lots of procedural generation and data-driven visual effects. Being able to efficiently pass arrays and struct data to shaders would allow more flexibility.
Describe the problem or limitation you are having in your project
Currently in Godot, the options for passing dynamic data to shaders are limited. Textures/samplers can work but require encoding data to textures. Uniforms only allow single values, not arrays or structs. This makes certain shader techniques difficult.
Describe the feature / enhancement and how it helps to overcome the problem or limitation
Implement shader storage buffer objects (SSBOs) to allow passing arrays, structs, and other custom data layouts to shaders.
Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams
The proposed interface is:
Here is an example of generating arrays for two attributes in an SSBO and assigning them to ssbo.data:
The key points:
This allows you to flexibly generate arrays matching the SSBO layout, then assign the data collectively.
The shader can then index into each array by name.
Allow to access data directly in SSBO like
If this enhancement will not be used often, can it be worked around with a few lines of script?
This could be worked around by encoding data in textures, but that is less flexible and optimal. Uniforms are limited to single values. SSBO provides the right level of abstraction.
Is there a reason why this should be core and not an add-on in the asset library?
Efficient data passing is a core graphics need. Textures work for some cases but are not optimal for all data. SSBO fills this gap and brings Godot up to par with other modern engines.
The text was updated successfully, but these errors were encountered: