-
-
Notifications
You must be signed in to change notification settings - Fork 3.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
Rework of #1203: Provide the camera's view matrix to shaders #1611
Conversation
Rebased on main and fixed up commit author that was messed up during rebase. |
layout(set = 0, binding = 0) uniform Camera { | ||
layout(set = 0, binding = 0) uniform CameraViewProj { |
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 (across every shader) is the one part of this PR that feel problematic to me, because it will break pretty much every single shader people have. On the other hand it seems messy to let the name remain just Camera.
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 seems to be a sensible change with an easy fix. My opinion is that it's better to make breaking changes like this sooner, in order to reduce the total code that must be fixed, and then add a note to our migration guides.
@@ -6,8 +6,9 @@ layout(location = 2) in vec2 Vertex_Uv; | |||
|
|||
layout(location = 0) out vec2 v_Uv; | |||
|
|||
layout(set = 0, binding = 0) uniform Camera { | |||
layout(set = 0, binding = 0) uniform CameraViewProj { |
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 binding is now incorrect and sprites no longer render
mat4 ViewProj; | ||
mat4 View; |
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 binding is now incorrect and sprite sheets no longer render
mat4 ViewProj; | ||
mat4 View; |
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 binding is now incorrect and ui no longer renders
mat4 ViewProj; | ||
}; | ||
layout(set = 0, binding = 1) uniform CameraView { |
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.
Neither of the forward shaders use CameraView, but removing it causes rendering to break (see the ui/sprite shaders, which are currently broken but can be "fixed" by adding CameraView).
As-is this implementation has the same problem I called out in #1203, but with the added downside of more boilerplate.
For this to be a solution, users need to be able to pull in only what they need.
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 review.
I made a wrong assumption that led me think these things would work: I assumed that the reason this worked for render resources was due to a difference between a uniform struct and separate bindings. I am a complete beginner when it comes to shaders... I did fail to test all the examples, I will remember better next time.
Clearly there’s much more going on under water in the render resource bindings. Is it using shader reflection to create bindgroups that only have the bindings used in the shaders?
If so, that seems useful and I’d love to find out how. But I’m finding the related code to be both dense and somewhat spread across different implementations. Can you point me in the right direction?
But wouldn't that also mean the cost of not having to have these bindings in some shader code goes up yet again? There's the cost of using multiple buffers instead of one. Multiple bindings. But now we even have to set up the bind groups for the camera every time the pipeline changes, I think?
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.
No worries! I can see why you would think that, given that the bindings provided by RenderResourceBindings are flexible in exactly that way. The reason it doesn't work here is that bind groups need to exactly match the shader layout. PassNode sets an explicit bind group for the camera (with two bindings), whereas RenderResourceBindings creates the exact bind group required to match the shader layout (if it doesn't already exist), which could have any number of bindings in any order.
Handling this case is non-trivial, especially if we want to do it generically. If every camera had a different name, we could just throw them into the global RenderResourceBindings and everything would magically work. However we dont want that for cameras.
I'm personally pretty attached to the idea of including pbr in 0.5, so I'm willing to consider short term solutions (such as the original impl: having a single combined binding/buffer and requiring that people include the camera position in every shader, or special-casing cameras to somehow allow both layouts).
I'll need to think a bit about this. Once I've wrapped up the other reviews i need to do, I'll probably spend some time on this. Feel free to explore the space too if you feel inclined!
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 I have a handle on this. Let me try to fix this PR.
@@ -32,8 +32,9 @@ const VERTEX_SHADER: &str = r#" | |||
layout(location = 0) in vec3 Vertex_Position; | |||
layout(location = 0) out vec4 v_Position; | |||
|
|||
layout(set = 0, binding = 0) uniform Camera { | |||
layout(set = 0, binding = 0) uniform CameraViewProj { | |||
mat4 ViewProj; |
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 example shaders are also broken.
I've taken a quick look at push constants, but they only reliably support 128 bytes, which is only enough for View and ViewProj. See https://docs.rs/wgpu/0.7.0/wgpu/struct.Limits.html#structfield.max_push_constant_size |
Yeah I'm also a little hesitant to use push constants as they aren't supported on the web: both WebGPU and (im assuming) bevy_webgl2. I don't want to support multiple render paths for those cases at this stage in bevy's development. |
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 I get it. It's the RenderPipelines.bindings
that holds all the bindings specific to an entity and DrawContext.set_bind_groups_from_bindings()
holds the logic to only set the bindings used by the current pipeline.
I think I can reproduce this for cameras in PassNode, now.
Hah. Nope. I'd need |
Alternative to #1203 and #1611 Camera bindings have historically been "hacked in". They were _required_ in all shaders and only supported a single Mat4. PBR (#1554) requires the CameraView matrix, but adding this using the "hacked" method forced users to either include all possible camera data in a single binding (#1203) or include all possible bindings (#1611). This approach instead assigns each "active camera" its own RenderResourceBindings, which are populated by CameraNode. The PassNode then retrieves (and initializes) the relevant bind groups for all render pipelines used by visible entities. * Enables any number of camera bindings , including zero (with any set or binding number ... set 0 should still be used to avoid rebinds). * Renames Camera binding to CameraViewProj * Adds CameraView binding
Solved by #1689 |
I reworked the code from #1203 based on this comment by Cart. Particularly, I've split the Camera Uniform into separate bindings and made it easy to extend with more bindings in the future. Such as the
CameraPos
needed in #1554.@lwansbrough I hope you don't mind. I also tried doing a PR against your fork, but github won't show/autocomplete your username or repositories in any fields for me.