Merge pull request #65800 from dsnopek/xr-resize-viewport-3

Fix XR rendering in 'opengl3' driver and expose true size via the Viewport node
This commit is contained in:
Clay John 2022-09-15 18:19:24 -07:00 committed by GitHub
commit 95df3e7c88
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 79 additions and 48 deletions

View file

@ -795,11 +795,20 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
stretch_transform = p_stretch_transform;
to_screen_rect = p_to_screen_rect;
if (p_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0);
}
#ifndef _3D_DISABLED
if (!use_xr) {
#endif
if (p_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0);
}
#ifndef _3D_DISABLED
} // if (!use_xr)
#endif
_update_global_transform();
update_configuration_warnings();
@ -813,6 +822,19 @@ void Viewport::_set_size(const Size2i &p_size, const Size2i &p_size_2d_override,
}
Size2i Viewport::_get_size() const {
#ifndef _3D_DISABLED
if (use_xr) {
if (XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface = XRServer::get_singleton()->get_primary_interface();
if (xr_interface.is_valid() && xr_interface->is_initialized()) {
Size2 xr_size = xr_interface->get_render_target_size();
return (Size2i)xr_size;
}
}
return Size2i();
}
#endif // _3D_DISABLED
return size;
}
@ -3612,9 +3634,20 @@ void Viewport::_propagate_exit_world_3d(Node *p_node) {
}
void Viewport::set_use_xr(bool p_use_xr) {
use_xr = p_use_xr;
if (use_xr != p_use_xr) {
use_xr = p_use_xr;
RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
RS::get_singleton()->viewport_set_use_xr(viewport, use_xr);
if (!use_xr) {
// Set viewport to previous size when exiting XR.
if (size_allocated) {
RS::get_singleton()->viewport_set_size(viewport, size.width, size.height);
} else {
RS::get_singleton()->viewport_set_size(viewport, 0, 0);
}
}
}
}
bool Viewport::is_using_xr() {

View file

@ -179,7 +179,7 @@ void RendererViewport::_configure_3d_render_buffers(Viewport *p_viewport) {
// to compensate for the loss of sharpness.
const float texture_mipmap_bias = log2f(MIN(scaling_3d_scale, 1.0)) + p_viewport->texture_mipmap_bias;
p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->get_view_count());
p_viewport->render_buffers->configure(p_viewport->render_target, Size2i(render_width, render_height), Size2(width, height), p_viewport->fsr_sharpness, texture_mipmap_bias, p_viewport->msaa_3d, p_viewport->screen_space_aa, p_viewport->use_taa, p_viewport->use_debanding, p_viewport->view_count);
}
}
}
@ -616,14 +616,7 @@ void RendererViewport::draw_viewports() {
if (xr_interface.is_valid()) {
// Override our size, make sure it matches our required size and is created as a stereo target
Size2 xr_size = xr_interface->get_render_target_size();
// Would have been nice if we could call viewport_set_size here,
// but alas that takes our RID and we now have our pointer,
// also we only check if view_count changes in render_target_set_size so we need to call that for this to reliably change
vp->occlusion_buffer_dirty = vp->occlusion_buffer_dirty || (vp->size != xr_size);
vp->size = xr_size;
uint32_t view_count = xr_interface->get_view_count();
RSG::texture_storage->render_target_set_size(vp->render_target, vp->size.x, vp->size.y, view_count);
_viewport_set_size(vp, xr_size.width, xr_size.height, xr_interface->get_view_count());
// Inform xr interface we're about to render its viewport, if this returns false we don't render
visible = xr_interface->pre_draw_viewport(vp->render_target);
@ -686,12 +679,17 @@ void RendererViewport::draw_viewports() {
// commit our eyes
Vector<BlitToScreen> blits = xr_interface->post_draw_viewport(vp->render_target, vp->viewport_to_screen_rect);
if (vp->viewport_to_screen != DisplayServer::INVALID_WINDOW_ID && blits.size() > 0) {
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
if (OS::get_singleton()->get_current_rendering_driver_name() == "opengl3") {
RSG::rasterizer->blit_render_targets_to_screen(vp->viewport_to_screen, blits.ptr(), blits.size());
RSG::rasterizer->end_frame(true);
} else {
if (!blit_to_screen_list.has(vp->viewport_to_screen)) {
blit_to_screen_list[vp->viewport_to_screen] = Vector<BlitToScreen>();
}
for (int b = 0; b < blits.size(); b++) {
blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
for (int b = 0; b < blits.size(); b++) {
blit_to_screen_list[vp->viewport_to_screen].push_back(blits[b]);
}
}
}
} else {
@ -777,7 +775,13 @@ void RendererViewport::viewport_set_use_xr(RID p_viewport, bool p_use_xr) {
}
viewport->use_xr = p_use_xr;
_configure_3d_render_buffers(viewport);
// Re-configure the 3D render buffers when disabling XR. They'll get
// re-configured when enabling XR in draw_viewports().
if (!p_use_xr) {
viewport->view_count = 1;
_configure_3d_render_buffers(viewport);
}
}
void RendererViewport::viewport_set_scaling_3d_mode(RID p_viewport, RS::ViewportScaling3DMode p_mode) {
@ -823,34 +827,27 @@ void RendererViewport::viewport_set_scaling_3d_scale(RID p_viewport, float p_sca
_configure_3d_render_buffers(viewport);
}
uint32_t RendererViewport::Viewport::get_view_count() {
uint32_t view_count = 1;
if (use_xr && XRServer::get_singleton() != nullptr) {
Ref<XRInterface> xr_interface;
xr_interface = XRServer::get_singleton()->get_primary_interface();
if (xr_interface.is_valid()) {
view_count = xr_interface->get_view_count();
}
}
return view_count;
}
void RendererViewport::viewport_set_size(RID p_viewport, int p_width, int p_height) {
ERR_FAIL_COND(p_width < 0 && p_height < 0);
Viewport *viewport = viewport_owner.get_or_null(p_viewport);
ERR_FAIL_COND(!viewport);
ERR_FAIL_COND_MSG(viewport->use_xr, "Cannot set viewport size when using XR");
viewport->size = Size2(p_width, p_height);
_viewport_set_size(viewport, p_width, p_height, 1);
}
uint32_t view_count = viewport->get_view_count();
RSG::texture_storage->render_target_set_size(viewport->render_target, p_width, p_height, view_count);
_configure_3d_render_buffers(viewport);
void RendererViewport::_viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count) {
Size2i new_size(p_width, p_height);
if (p_viewport->size != new_size || p_viewport->view_count != p_view_count) {
p_viewport->size = new_size;
p_viewport->view_count = p_view_count;
viewport->occlusion_buffer_dirty = true;
RSG::texture_storage->render_target_set_size(p_viewport->render_target, p_width, p_height, p_view_count);
_configure_3d_render_buffers(p_viewport);
p_viewport->occlusion_buffer_dirty = true;
}
}
void RendererViewport::viewport_set_active(RID p_viewport, bool p_active) {
@ -890,7 +887,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// If using OpenGL we can optimize this operation by rendering directly to system_fbo
// instead of rendering to fbo and copying to system_fbo after
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->get_view_count());
RSG::texture_storage->render_target_set_size(viewport->render_target, p_rect.size.x, p_rect.size.y, viewport->view_count);
RSG::texture_storage->render_target_set_position(viewport->render_target, p_rect.position.x, p_rect.position.y);
}
@ -900,7 +897,7 @@ void RendererViewport::viewport_attach_to_screen(RID p_viewport, const Rect2 &p_
// if render_direct_to_screen was used, reset size and position
if (RSG::rasterizer->is_low_end() && viewport->viewport_render_direct_to_screen) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
viewport->viewport_to_screen_rect = Rect2();
@ -919,7 +916,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if disabled, reset render_target size and position
if (!p_enable) {
RSG::texture_storage->render_target_set_position(viewport->render_target, 0, 0);
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->get_view_count());
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->size.x, viewport->size.y, viewport->view_count);
}
RSG::texture_storage->render_target_set_direct_to_screen(viewport->render_target, p_enable);
@ -927,7 +924,7 @@ void RendererViewport::viewport_set_render_direct_to_screen(RID p_viewport, bool
// if attached to screen already, setup screen size and position, this needs to happen after setting flag to avoid an unnecessary buffer allocation
if (RSG::rasterizer->is_low_end() && viewport->viewport_to_screen_rect != Rect2() && p_enable) {
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->get_view_count());
RSG::texture_storage->render_target_set_size(viewport->render_target, viewport->viewport_to_screen_rect.size.x, viewport->viewport_to_screen_rect.size.y, viewport->view_count);
RSG::texture_storage->render_target_set_position(viewport->render_target, viewport->viewport_to_screen_rect.position.x, viewport->viewport_to_screen_rect.position.y);
}
}

View file

@ -54,6 +54,7 @@ public:
Size2i internal_size;
Size2i size;
uint32_t view_count;
RID camera;
RID scenario;
@ -150,6 +151,7 @@ public:
RendererScene::RenderInfo render_info;
Viewport() {
view_count = 1;
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
@ -176,8 +178,6 @@ public:
time_gpu_begin = 0;
time_gpu_end = 0;
}
uint32_t get_view_count();
};
HashMap<String, RID> timestamp_vp_map;
@ -196,6 +196,7 @@ public:
private:
Vector<Viewport *> _sort_active_viewports();
void _viewport_set_size(Viewport *p_viewport, int p_width, int p_height, uint32_t p_view_count);
void _configure_3d_render_buffers(Viewport *p_viewport);
void _draw_3d(Viewport *p_viewport);
void _draw_viewport(Viewport *p_viewport);