-
-
Notifications
You must be signed in to change notification settings - Fork 35.5k
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
WebGPURenderer: StorageBufferNode
Support reading external elements in the WebGL Backend
#27661
WebGPURenderer: StorageBufferNode
Support reading external elements in the WebGL Backend
#27661
Conversation
const width = Math.floor( square ); | ||
const height = Math.ceil( square ); | ||
|
||
const pboTexture = new DataTexture( attribute.array, width, height, RGBAFormat, FloatType ); |
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.
The circular-reference problem is because of UniformNode
in ArrayElementNode
, UniformNode
will use ShaderNode
and ShaderNode
will include try ArrayElementNode
again.
I think it would be better to move this uniform creation block to GLSLNodeBuilder
something like builder.getPBOUniform()
for example, this could fix the circular reference problem too.
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 think we have to consider a new Node, similar to what was done in BufferAttributeNode
and buffer.toAttribute()
as usage. It could be buffer.toTexture()
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 agree, this feels like something that should better be placed in GLSLNodeBuilder.
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.
Also consider add/move it to StorageBufferNode.element()
to avoid checks a little, and return and new Node to keep operations more organized, it can even be a StorageArrayElementNode
.
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.
Thanks for the feedbacks!
The downside of buffer.toTexture()
would be that this implies that somehow the developer would expect that something happens in the WebGPU
Backend too.
This feature is more like a patch to fix the fact WebGL cannot access other element of array buffers rather than a new feature such as toAttribute()
.
I think I can try to move all this part to GLSLNodeBuilder
but I'm not sure on how to create a Node here. Maybe once everything works we can think about creating a new Node specific to Pixel Buffer Object
, but once again it's only a WebGL thing.
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 be happy to help you with this, let me know when the PR is ready for review so I can analyze it again.
About the example what do you think about renaming it to webgpu_storage_sorting
?
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.
Sounds good to me! Thanks a lot for this 😊
const propertyNameTexture = builder.getPropertyName( nodeUniform ); | ||
|
||
const snippet = /* glsl */` | ||
texelFetch( |
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 think we can also move to GLSLNodeBuilder
similar to what happens in builder.generateTextureLoad()
.
I finished the implementation. The main purpose of this PR is basically to improve the compute shading support by allowing reading data from external elements in the WebGL Backend. The example is very dev oriented but I believe this will be useful for E2E tests in the future and prevent breaking things in regards to storage buffers. Also it should help some very specific use case such as simulations for advanced developers in the future. It does support different formats even though that's the initial PR ( Also my detection of the type of the target node is very weak in I added 2 I believe this can be improved even more in the future but that's already a nice additional to compute shading fallback in my opinion. It's now ready for review as I lack of knowledge on the node part. 👍 |
return nodeSnippet; | ||
snippet = nodeSnippet; | ||
|
||
// TODO: How to properly detect if the node will be used as an assign target? |
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 think you should just check if output
is 'void'
(i.e. just change 'assign'
to 'void'
here and in AssignNode).
Is my suggestion above also not working? 🤔 |
} else { | ||
|
||
transformBuffers[ i ].switchBuffers(); | ||
//this.textureUtils.copyBufferToTexture( transformBuffers[ i ].transformBuffer, transformBuffers[ i ].pbo ); |
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.
@RenaudRohlinger I have a performance issue, could you open the example webgpu_compute_particles
and uncomment the PBO line here? Perhaps you have any suggestions as to what it could be?
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.
webgpu_compute_particles
shouldn't need to use PBO
so it's probably some sort of infinite loop. It's not related to the PBO line, if you comment transformBuffers[ i ].switchBuffers();
the buffers will not be swapped anymore as they should and all compute examples will have these performances issues @sunag
@LeviPesin It's not clear to me that this would resolve the issue. There seems to be more related things. |
@sunag I just pushed a patch to handle cases where we would use basic dual-buffer compute shaders and then later on, on the same storage buffer, read from other elements and so switch to PBO. The remaining issue in |
By the way, I just realized that the performance issue in webgpu_compute_particles and webgpu_compute_particles_rain is due to overdraw. This happens because all the particles are positioned at 0,0,0 and are not being properly updated, as the dual-buffer isn't being called. /cc @sunag |
Would it be correct to say that the objective of the PR is to use PBO only in |
Yes, that is correct. That's why I initially thought it would be safer and easier to introduce a third parameter to the storage buffer. For instance, we could have This approach would makes sense in my opinion because accessing external elements is already quite advanced. /cc @sunag |
This makes sense, and will be necessary to implement something since we need to have this information to manipulate the PBO, I'm thinking about implementing a |
@RenaudRohlinger I added new TSL function Now the examples is working, including |
Nice! I love this pattern. |
StorageBufferNode
Support reading external elements in the WebGL Backend
Thanks for all the help @sunag! Let's give it a try 😊 I will look into adding writing access via full |
Names |
Related issue: #27642
Description
Compute shaders in the WebGL backend can now read other elements just like the
storage_buffer
in WebGPU automatically.Using
storageObject
will convert the dual-buffer transform feedback system into a transform feedback system with a single buffer as output and a Pixel Buffer Object (PBO) texture as input.Here's a basic demo that alternates the order of the array buffer (element(100) becomes element (0) and so on):
https://raw.githack.com/renaudrohlinger/three.js/utsubo/feat/storage_pbo/examples/webgpu_storage_buffer.html
What's cool in this example is that the left side is using the WebGPU Backend and the right side is a WebGL Backend. 😁
This contribution is funded by Utsubo