From d357cbdecadece8d297d4caa00198628c0c5d0a2 Mon Sep 17 00:00:00 2001 From: Bastiaan Olij Date: Sun, 10 Nov 2019 19:30:20 +1100 Subject: [PATCH] Add special external MSAA modes for GLES2 Rift S/Quest and OpenXR optimisation --- doc/classes/VisualServer.xml | 6 +++ drivers/gles2/rasterizer_storage_gles2.cpp | 51 ++++++++++++++++++---- drivers/gles2/rasterizer_storage_gles2.h | 5 ++- drivers/gles3/rasterizer_storage_gles3.cpp | 2 +- scene/main/scene_tree.cpp | 2 +- scene/main/viewport.cpp | 4 +- servers/visual_server.cpp | 2 + servers/visual_server.h | 2 + 8 files changed, 60 insertions(+), 14 deletions(-) diff --git a/doc/classes/VisualServer.xml b/doc/classes/VisualServer.xml index b95b970816f40..18b08421a13af 100644 --- a/doc/classes/VisualServer.xml +++ b/doc/classes/VisualServer.xml @@ -4238,6 +4238,12 @@ Multisample antialiasing is set to 16×. + + Multisample antialiasing is set to 2× on external texture. Special mode for GLES2 VR for the Oculus Quest. + + + Multisample antialiasing is set to 4× on external texture. Special mode for GLES2 VR for the Oculus Quest. + The Viewport does not render 3D but samples. diff --git a/drivers/gles2/rasterizer_storage_gles2.cpp b/drivers/gles2/rasterizer_storage_gles2.cpp index 9d9bceb243db0..38b8f65319006 100644 --- a/drivers/gles2/rasterizer_storage_gles2.cpp +++ b/drivers/gles2/rasterizer_storage_gles2.cpp @@ -4694,7 +4694,7 @@ void RasterizerStorageGLES2::_render_target_allocate(RenderTarget *rt) { /* For MSAA */ #ifndef JAVASCRIPT_ENABLED - if (rt->msaa != VS::VIEWPORT_MSAA_DISABLED && config.multisample_supported) { + if (rt->msaa >= VS::VIEWPORT_MSAA_2X && rt->msaa <= VS::VIEWPORT_MSAA_16X && config.multisample_supported) { rt->multisample_active = true; @@ -5090,6 +5090,11 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar // free this glDeleteFramebuffers(1, &rt->external.fbo); + // and this + if (rt->external.depth != 0) { + glDeleteRenderbuffers(1, &rt->external.depth); + } + // clean up our texture Texture *t = texture_owner.get(rt->external.texture); t->alloc_height = 0; @@ -5102,6 +5107,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar rt->external.fbo = 0; rt->external.color = 0; + rt->external.depth = 0; } } else { Texture *t; @@ -5136,6 +5142,7 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar t->render_target = rt; rt->external.texture = texture_owner.make_rid(t); + } else { // bind our frame buffer glBindFramebuffer(GL_FRAMEBUFFER, rt->external.fbo); @@ -5154,16 +5161,42 @@ void RasterizerStorageGLES2::render_target_set_external_texture(RID p_render_tar t->alloc_height = rt->width; t->alloc_width = rt->height; - // is there a point to setting the internal formats? we don't know them.. + // Switch our texture on our frame buffer +#if ANDROID_ENABLED + if (rt->msaa >= VS::VIEWPORT_MSAA_EXT_2X && rt->msaa <= VS::VIEWPORT_MSAA_EXT_4X) { + // This code only applies to the Oculus Go and Oculus Quest. Due to the the tiled nature + // of the GPU we can do a single render pass by rendering directly into our texture chains + // texture and apply MSAA as we render. + + // On any other hardware these two modes are ignored and we do not have any MSAA, + // the normal MSAA modes need to be used to enable our two pass approach + + static const int msaa_value[] = { 2, 4 }; + int msaa = msaa_value[rt->msaa - VS::VIEWPORT_MSAA_EXT_2X]; + + if (rt->external.depth == 0) { + // create a multisample depth buffer, we're not reusing Godots because Godot's didn't get created.. + glGenRenderbuffers(1, &rt->external.depth); + glBindRenderbuffer(GL_RENDERBUFFER, rt->external.depth); + glRenderbufferStorageMultisample(GL_RENDERBUFFER, msaa, config.depth_internalformat, rt->width, rt->height); + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->external.depth); + } - // set our texture as the destination for our framebuffer - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); + // and set our external texture as the texture... + glFramebufferTexture2DMultisample(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0, msaa); - // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :) - if (config.support_depth_texture) { - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); - } else { - glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + } else +#endif + { + // set our texture as the destination for our framebuffer + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, p_texture_id, 0); + + // seeing we're rendering into this directly, better also use our depth buffer, just use our existing one :) + if (config.support_depth_texture) { + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, rt->depth, 0); + } else { + glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rt->depth); + } } // check status and unbind diff --git a/drivers/gles2/rasterizer_storage_gles2.h b/drivers/gles2/rasterizer_storage_gles2.h index 27f06074ed229..6de530d8c3340 100644 --- a/drivers/gles2/rasterizer_storage_gles2.h +++ b/drivers/gles2/rasterizer_storage_gles2.h @@ -1182,10 +1182,13 @@ class RasterizerStorageGLES2 : public RasterizerStorage { struct External { GLuint fbo; GLuint color; + GLuint depth; RID texture; External() : - fbo(0) { + fbo(0), + color(0), + depth(0) { } } external; diff --git a/drivers/gles3/rasterizer_storage_gles3.cpp b/drivers/gles3/rasterizer_storage_gles3.cpp index f94020b91885d..71737426a9c20 100644 --- a/drivers/gles3/rasterizer_storage_gles3.cpp +++ b/drivers/gles3/rasterizer_storage_gles3.cpp @@ -6961,7 +6961,7 @@ void RasterizerStorageGLES3::_render_target_allocate(RenderTarget *rt) { rt->buffers.active = true; - static const int msaa_value[] = { 0, 2, 4, 8, 16 }; + static const int msaa_value[] = { 0, 2, 4, 8, 16, 4, 16 }; // MSAA_EXT_nX is a GLES2 temporary hack ignored in GLES3 for now... int msaa = msaa_value[rt->msaa]; int max_samples = 0; diff --git a/scene/main/scene_tree.cpp b/scene/main/scene_tree.cpp index 5653049060705..78ceccfca20f6 100644 --- a/scene/main/scene_tree.cpp +++ b/scene/main/scene_tree.cpp @@ -2066,7 +2066,7 @@ SceneTree::SceneTree() { int ref_atlas_subdiv = GLOBAL_DEF("rendering/quality/reflections/atlas_subdiv", 8); ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/reflections/atlas_subdiv", PropertyInfo(Variant::INT, "rendering/quality/reflections/atlas_subdiv", PROPERTY_HINT_RANGE, "0,32,or_greater")); //next_power_of_2 will return a 0 as min value int msaa_mode = GLOBAL_DEF("rendering/quality/filters/msaa", 0); - ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x")); + ProjectSettings::get_singleton()->set_custom_property_info("rendering/quality/filters/msaa", PropertyInfo(Variant::INT, "rendering/quality/filters/msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,External 2x,External 4x")); root->set_msaa(Viewport::MSAA(msaa_mode)); GLOBAL_DEF("rendering/quality/depth/hdr", true); diff --git a/scene/main/viewport.cpp b/scene/main/viewport.cpp index 1af88171f618c..417652fe5deb4 100644 --- a/scene/main/viewport.cpp +++ b/scene/main/viewport.cpp @@ -2955,7 +2955,7 @@ int Viewport::gui_get_canvas_sort_index() { void Viewport::set_msaa(MSAA p_msaa) { - ERR_FAIL_INDEX(p_msaa, 5); + ERR_FAIL_INDEX(p_msaa, 7); if (msaa == p_msaa) return; msaa = p_msaa; @@ -3186,7 +3186,7 @@ void Viewport::_bind_methods() { ADD_PROPERTY(PropertyInfo(Variant::BOOL, "transparent_bg"), "set_transparent_background", "has_transparent_background"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "handle_input_locally"), "set_handle_input_locally", "is_handling_input_locally"); ADD_GROUP("Rendering", ""); - ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x"), "set_msaa", "get_msaa"); + ADD_PROPERTY(PropertyInfo(Variant::INT, "msaa", PROPERTY_HINT_ENUM, "Disabled,2x,4x,8x,16x,External 2x,External 4x"), "set_msaa", "get_msaa"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "hdr"), "set_hdr", "get_hdr"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "disable_3d"), "set_disable_3d", "is_3d_disabled"); ADD_PROPERTY(PropertyInfo(Variant::BOOL, "keep_3d_linear"), "set_keep_3d_linear", "get_keep_3d_linear"); diff --git a/servers/visual_server.cpp b/servers/visual_server.cpp index b095f24212363..a1ba946d8c86c 100644 --- a/servers/visual_server.cpp +++ b/servers/visual_server.cpp @@ -2171,6 +2171,8 @@ void VisualServer::_bind_methods() { BIND_ENUM_CONSTANT(VIEWPORT_MSAA_4X); BIND_ENUM_CONSTANT(VIEWPORT_MSAA_8X); BIND_ENUM_CONSTANT(VIEWPORT_MSAA_16X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_2X); + BIND_ENUM_CONSTANT(VIEWPORT_MSAA_EXT_4X); BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D); BIND_ENUM_CONSTANT(VIEWPORT_USAGE_2D_NO_SAMPLING); diff --git a/servers/visual_server.h b/servers/visual_server.h index 1c1b04f1989c7..b1daf87e5661e 100644 --- a/servers/visual_server.h +++ b/servers/visual_server.h @@ -658,6 +658,8 @@ class VisualServer : public Object { VIEWPORT_MSAA_4X, VIEWPORT_MSAA_8X, VIEWPORT_MSAA_16X, + VIEWPORT_MSAA_EXT_2X, + VIEWPORT_MSAA_EXT_4X, }; virtual void viewport_set_msaa(RID p_viewport, ViewportMSAA p_msaa) = 0;