-
-
Notifications
You must be signed in to change notification settings - Fork 22k
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
Allow using custom Rect2i
for rendering with OpenXR
#99407
Conversation
7054b69
to
ae0a7a4
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.
Thanks!
I tested this together with PR GodotVR/godot_openxr_vendors#226, and it appears to be working great! (I have notes about the performance gains I'm seeing, but that's more related to the META_recommended_layer_resolution
extension, so I'll write about it on the other PR.)
The code looks good to me as well.
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.
Looks good!
Added some minor comments to address.
modules/openxr/openxr_api.cpp
Outdated
Rect2i new_render_region = Rect2i(Point2i(0, 0), render_state.main_swapchain_size); | ||
if (render_region != Rect2i()) { | ||
new_render_region = render_region; | ||
} |
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.
Can be replaced by the following:
Rect2i new_render_region = (render_region != Rect2i()) ? render_region : Rect2i(Point2i(0, 0), render_state.main_swapchain_size);
In addition:
- The
Rect2i
documentation states thatRect2i() == false
, so we can replacerender_region != Rect2i()
withrender_region != false
Point2i(0, 0)
can be replaced byVector2i.ZERO
- Do we expect
Rect2i(Point2i(0, 0), render_state.main_swapchain_size)
to change every frame?
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've made the suggested replacement, thanks! As to your other points, the Rect2i() == false
and Vector2i.ZERO
suggestions I believe would only work in editor?
Rect2i(Point2i(0, 0), render_state.main_swapchain_size)
would typically remain the same, it would only be resized if a new swapchain was created (with a different size). Maybe on swapchain creation I could just store the size in a variable rather than creating this every frame.
ae0a7a4
to
5e15ae8
Compare
@Mickeon / @AThousandShips thanks so much for the review! I believe I've applied all your suggested changes. :) |
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.
Docs a-okay now, assuming accuracy.
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.
Looks really cool as far as functionality goes, it'll be interesting to see if we can create our own logic for altering the render region even outside of this extension. XrSwapchainSubImage.imageRect
is available in the core.
Similarly I wonder if making the render region core viewport functionality instead of an override makes sense. The use cases here extend beyond XR, being able to dynamically effect the render resolution without recreating all buffers could be useful.
Couple of things that stand out that need to be discussed further:
- Dealing with the pesky
render_target_size_multiplier
feature we added to OpenXR, we talked about this I think in the XR meeting already, but if this is set to anything other than its default 1.0, especially if its set smaller, it could cause havoc when combined with this. - The implementation of
render_region
on the OpenXR side, is not thread safe. When rendering happens on a separate thread you've created a possibility for the render region to be set for a new frame, while a frame is being rendered, with the possibility that render result and render region don't match. You have to take the same approach as a number of other properties have, where you have a copy inrender_state
that is set through callingcall_on_render_thread
. Seeset_render_target_size_multiplier
andset_render_state_multiplier
as an example. - I'm not sure I like us exposing the projection layer. Here too there is a high risk of thread issues and it will be easy to break things. Especially when future work will require modifications that will clash with what is done in an extension. We spoke about this before and that we probably don't have any other choice, but I'd like to know more of the reasoning behind this and it would be good to have this properly documented. If we can find a cleaner way to expose the required functionality that would have my preference, but without knowing more I can't think of good suggestions.
- What is the impact on other features? Does the VRS map need to be calculated based on the render_region, how are build in effects effected especially when this functionality is adopted on PCVR with the Forward+ renderer. Etc.
d61e5ec
to
f5de8a5
Compare
Thanks for the review @BastiaanOlij!
|
7941cb8
to
625526b
Compare
@BastiaanOlij the VRS map did indeed need to be calculated based on |
625526b
to
36181d1
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.
I think we need to clean up the API here a bit. This feature is implemented with 3 assumptions that I think are all incorrect:
- We are always using an overridden render target (alternatively stated "we are always using XR")
- The render target is always the same size as the render buffers
- We are always using dynamic scaling
Building on Bastiaan's comments above. This API needs to consider dynamic scaling on non-XR devices and expose an API that can be accessed from rather than building in an API that can only be used from XR
@@ -2011,7 +2011,8 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co | |||
} | |||
if (needs_pre_resolve) { | |||
//pre clear the depth framebuffer, as AMD (and maybe others?) use compute for it, and barrier other compute shaders. | |||
RD::get_singleton()->draw_list_begin(depth_framebuffer, RD::DRAW_CLEAR_ALL, depth_pass_clear, 0.0f); | |||
Rect2i region = RendererRD::TextureStorage::get_singleton()->render_target_get_override_render_region(rb->get_render_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.
We should clean this up to consider the case where there is no render target override. Most of the time when this code runs, it will be in a non-XR environment, so we shouldn't add something that assumes we are in XR and using dynamic scaling.
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've updated it so that render_region
is no longer a part of the override/xr stuff, it's now just a property of the RenderTarget
struct.
8479cfd
to
9e0bda1
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.
Discussed in the rendering meeting. We discussed that the render region should be stored in the RenderData struct.
You can store it here: https://github.com/godotengine/godot/blob/fafc07335bdecacd96b548c4119fbe1f47ee5866/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp#L1221C31-L1221C105
Then, throughout rendering we can apply the region consistently by accessing render data
Also noticed that the transparent pass is missing the render region in the mobile renderer, so it needs to be used there.
9e0bda1
to
c618ec5
Compare
@clayjohn thanks for sharing the suggested changes! I've applied them in my latest push. :) |
Looks good to me. My only cringe is still the get_projection_layer being exposed, but looking at how it is used for Maybe we should define the function as |
c618ec5
to
e7f6b7e
Compare
Makes sense to me! I've updated the function signature. |
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.
Great work!
Thanks! |
This PR adds the ability to set a
render_region
Rect2i
property inOpenXRAPI
, which is passed along to the renderer's override properties. If a customRect2i
is set, it will be applied to the rendered image rects. This is meant to be used with something like theXR_META_recommended_layer_resolution
OpenXR extension.The newly added
OpenXRAPI
functionsset_render_region()
andget_projection_layer()
have been exposed to GDExtension to allow for the implementation ofXR_META_recommended_layer_resolution
in the vendor repo.