Skip to content
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

Fix XR rendering in 'opengl3' driver and expose true size via the Viewport node #65800

Merged
merged 1 commit into from
Sep 16, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 40 additions & 7 deletions scene/main/viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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;
}

Expand Down Expand Up @@ -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() {
Expand Down
75 changes: 36 additions & 39 deletions servers/rendering/renderer_viewport.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}

Expand All @@ -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();
Expand All @@ -919,15 +916,15 @@ 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);
viewport->viewport_render_direct_to_screen = p_enable;

// 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);
}
}
Expand Down
5 changes: 3 additions & 2 deletions servers/rendering/renderer_viewport.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ class RendererViewport {

Size2i internal_size;
Size2i size;
uint32_t view_count;
RID camera;
RID scenario;

Expand Down Expand Up @@ -150,6 +151,7 @@ class RendererViewport {
RendererScene::RenderInfo render_info;

Viewport() {
view_count = 1;
update_mode = RS::VIEWPORT_UPDATE_WHEN_VISIBLE;
clear_mode = RS::VIEWPORT_CLEAR_ALWAYS;
transparent_bg = false;
Expand All @@ -176,8 +178,6 @@ class RendererViewport {
time_gpu_begin = 0;
time_gpu_end = 0;
}

uint32_t get_view_count();
};

HashMap<String, RID> timestamp_vp_map;
Expand All @@ -196,6 +196,7 @@ class RendererViewport {

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);
Expand Down