2022-08-04 08:40:39 +00:00
/**************************************************************************/
/* render_scene_buffers_gles3.cpp */
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
/* */
/* Permission is hereby granted, free of charge, to any person obtaining */
/* a copy of this software and associated documentation files (the */
/* "Software"), to deal in the Software without restriction, including */
/* without limitation the rights to use, copy, modify, merge, publish, */
/* distribute, sublicense, and/or sell copies of the Software, and to */
/* permit persons to whom the Software is furnished to do so, subject to */
/* the following conditions: */
/* */
/* The above copyright notice and this permission notice shall be */
/* included in all copies or substantial portions of the Software. */
/* */
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
/**************************************************************************/
# ifdef GLES3_ENABLED
# include "render_scene_buffers_gles3.h"
2023-10-26 01:10:38 +00:00
# include "config.h"
2022-08-04 08:40:39 +00:00
# include "texture_storage.h"
2023-10-26 01:10:38 +00:00
# include "utilities.h"
# ifdef ANDROID_ENABLED
# define glFramebufferTextureMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultiviewOVR
# define glTexStorage3DMultisample GLES3::Config::get_singleton()->eglTexStorage3DMultisample
# define glFramebufferTexture2DMultisampleEXT GLES3::Config::get_singleton()->eglFramebufferTexture2DMultisampleEXT
# define glFramebufferTextureMultisampleMultiviewOVR GLES3::Config::get_singleton()->eglFramebufferTextureMultisampleMultiviewOVR
# endif // ANDROID_ENABLED
// Will only be defined if GLES 3.2 headers are included
# ifndef GL_TEXTURE_2D_MULTISAMPLE_ARRAY
# define GL_TEXTURE_2D_MULTISAMPLE_ARRAY 0x9102
# endif
2022-08-04 08:40:39 +00:00
2024-01-19 05:14:36 +00:00
RenderSceneBuffersGLES3 : : RenderSceneBuffersGLES3 ( ) {
for ( int i = 0 ; i < 4 ; i + + ) {
glow . levels [ i ] . color = 0 ;
glow . levels [ i ] . fbo = 0 ;
}
}
2022-08-04 08:40:39 +00:00
RenderSceneBuffersGLES3 : : ~ RenderSceneBuffersGLES3 ( ) {
free_render_buffer_data ( ) ;
}
2023-11-08 20:54:29 +00:00
void RenderSceneBuffersGLES3 : : _rt_attach_textures ( GLuint p_color , GLuint p_depth , GLsizei p_samples , uint32_t p_view_count ) {
if ( p_view_count > 1 ) {
if ( p_samples > 1 ) {
# if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
glFramebufferTextureMultisampleMultiviewOVR ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , p_color , 0 , p_samples , 0 , p_view_count ) ;
glFramebufferTextureMultisampleMultiviewOVR ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , p_depth , 0 , p_samples , 0 , p_view_count ) ;
# else
ERR_PRINT_ONCE ( " Multiview MSAA isn't supported on this platform. " ) ;
# endif
} else {
# ifndef IOS_ENABLED
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , p_color , 0 , 0 , p_view_count ) ;
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , p_depth , 0 , 0 , p_view_count ) ;
# else
ERR_PRINT_ONCE ( " Multiview isn't supported on this platform. " ) ;
# endif
}
} else {
if ( p_samples > 1 ) {
# ifdef ANDROID_ENABLED
glFramebufferTexture2DMultisampleEXT ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , p_color , 0 , p_samples ) ;
glFramebufferTexture2DMultisampleEXT ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_TEXTURE_2D , p_depth , 0 , p_samples ) ;
# else
ERR_PRINT_ONCE ( " MSAA via EXT_multisampled_render_to_texture isn't supported on this platform. " ) ;
# endif
} else {
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , p_color , 0 ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_TEXTURE_2D , p_depth , 0 ) ;
}
}
}
2023-10-26 01:10:38 +00:00
GLuint RenderSceneBuffersGLES3 : : _rt_get_cached_fbo ( GLuint p_color , GLuint p_depth , GLsizei p_samples , uint32_t p_view_count ) {
FBDEF new_fbo ;
2023-11-08 20:54:29 +00:00
# if defined(ANDROID_ENABLED) || defined(WEB_ENABLED)
2023-10-26 01:10:38 +00:00
// There shouldn't be more then 3 entries in this...
for ( const FBDEF & cached_fbo : msaa3d . cached_fbos ) {
if ( cached_fbo . color = = p_color & & cached_fbo . depth = = p_depth ) {
return cached_fbo . fbo ;
}
}
new_fbo . color = p_color ;
new_fbo . depth = p_depth ;
glGenFramebuffers ( 1 , & new_fbo . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , new_fbo . fbo ) ;
2023-11-08 20:54:29 +00:00
_rt_attach_textures ( p_color , p_depth , p_samples , p_view_count ) ;
2023-10-26 01:10:38 +00:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
WARN_PRINT ( " Could not create 3D MSAA framebuffer, status: " + GLES3 : : TextureStorage : : get_singleton ( ) - > get_framebuffer_error ( status ) ) ;
glDeleteFramebuffers ( 1 , & new_fbo . fbo ) ;
new_fbo . fbo = 0 ;
} else {
// cache it!
msaa3d . cached_fbos . push_back ( new_fbo ) ;
}
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
# endif
return new_fbo . fbo ;
}
2023-07-07 05:24:20 +00:00
void RenderSceneBuffersGLES3 : : configure ( const RenderSceneBuffersConfiguration * p_config ) {
2023-10-26 01:10:38 +00:00
GLES3 : : TextureStorage * texture_storage = GLES3 : : TextureStorage : : get_singleton ( ) ;
GLES3 : : Config * config = GLES3 : : Config : : get_singleton ( ) ;
free_render_buffer_data ( ) ;
internal_size = p_config - > get_internal_size ( ) ;
target_size = p_config - > get_target_size ( ) ;
scaling_3d_mode = p_config - > get_scaling_3d_mode ( ) ;
2023-07-07 05:24:20 +00:00
//fsr_sharpness = p_config->get_fsr_sharpness();
//texture_mipmap_bias = p_config->get_texture_mipmap_bias();
render_target = p_config - > get_render_target ( ) ;
2023-10-26 01:10:38 +00:00
msaa3d . mode = p_config - > get_msaa_3d ( ) ;
2023-07-07 05:24:20 +00:00
//screen_space_aa = p_config->get_screen_space_aa();
//use_debanding = p_config->get_use_debanding();
2023-10-26 01:10:38 +00:00
view_count = config - > multiview_supported ? p_config - > get_view_count ( ) : 1 ;
2022-08-04 08:40:39 +00:00
2023-10-26 01:10:38 +00:00
bool use_multiview = view_count > 1 ;
2024-01-19 05:14:36 +00:00
// Get color format data from our render target so we match those
if ( render_target . is_valid ( ) ) {
color_internal_format = texture_storage - > render_target_get_color_internal_format ( render_target ) ;
color_format = texture_storage - > render_target_get_color_format ( render_target ) ;
color_type = texture_storage - > render_target_get_color_type ( render_target ) ;
color_format_size = texture_storage - > render_target_get_color_format_size ( render_target ) ;
} else {
// reflection probe? or error?
color_internal_format = GL_RGBA8 ;
color_format = GL_RGBA ;
color_type = GL_UNSIGNED_BYTE ;
color_format_size = 4 ;
}
2023-10-26 01:10:38 +00:00
// Check our scaling mode
if ( scaling_3d_mode ! = RS : : VIEWPORT_SCALING_3D_MODE_OFF & & internal_size . x = = 0 & & internal_size . y = = 0 ) {
// Disable, no size set.
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_OFF ;
} else if ( scaling_3d_mode ! = RS : : VIEWPORT_SCALING_3D_MODE_OFF & & internal_size = = target_size ) {
// If size matches, we won't use scaling.
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_OFF ;
} else if ( scaling_3d_mode ! = RS : : VIEWPORT_SCALING_3D_MODE_OFF & & scaling_3d_mode ! = RS : : VIEWPORT_SCALING_3D_MODE_BILINEAR ) {
// We only support bilinear scaling atm.
WARN_PRINT_ONCE ( " GLES only supports bilinear scaling. " ) ;
scaling_3d_mode = RS : : VIEWPORT_SCALING_3D_MODE_BILINEAR ;
}
2024-01-19 05:14:36 +00:00
// Check if we support MSAA.
if ( msaa3d . mode ! = RS : : VIEWPORT_MSAA_DISABLED & & internal_size . x = = 0 & & internal_size . y = = 0 ) {
// Disable, no size set.
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
} else if ( ! use_multiview & & msaa3d . mode ! = RS : : VIEWPORT_MSAA_DISABLED & & ! config - > msaa_supported & & ! config - > rt_msaa_supported ) {
WARN_PRINT_ONCE ( " MSAA is not supported on this device. " ) ;
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
} else if ( use_multiview & & msaa3d . mode ! = RS : : VIEWPORT_MSAA_DISABLED & & ! config - > msaa_multiview_supported & & ! config - > rt_msaa_multiview_supported ) {
WARN_PRINT_ONCE ( " Multiview MSAA is not supported on this device. " ) ;
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
}
// We don't create our buffers right away because post effects can be made active at any time and change our buffer configuration.
}
void RenderSceneBuffersGLES3 : : _check_render_buffers ( ) {
GLES3 : : TextureStorage * texture_storage = GLES3 : : TextureStorage : : get_singleton ( ) ;
GLES3 : : Config * config = GLES3 : : Config : : get_singleton ( ) ;
ERR_FAIL_COND ( view_count = = 0 ) ;
bool use_internal_buffer = scaling_3d_mode ! = RS : : VIEWPORT_SCALING_3D_MODE_OFF | | glow . glow_enabled ;
uint32_t depth_format_size = 3 ;
bool use_multiview = view_count > 1 ;
if ( ( ! use_internal_buffer | | internal3d . color ! = 0 ) & & ( msaa3d . mode = = RS : : VIEWPORT_MSAA_DISABLED | | msaa3d . color ! = 0 ) ) {
// already setup!
return ;
}
2023-10-26 01:10:38 +00:00
if ( use_internal_buffer ) {
// Setup our internal buffer.
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D ;
// Create our color buffer.
glGenTextures ( 1 , & internal3d . color ) ;
glBindTexture ( texture_target , internal3d . color ) ;
if ( use_multiview ) {
glTexImage3D ( texture_target , 0 , color_internal_format , internal_size . x , internal_size . y , view_count , 0 , color_format , color_type , nullptr ) ;
} else {
glTexImage2D ( texture_target , 0 , color_internal_format , internal_size . x , internal_size . y , 0 , color_format , color_type , nullptr ) ;
}
glTexParameteri ( texture_target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( internal3d . color , internal_size . x * internal_size . y * view_count * color_format_size , " 3D color texture " ) ;
2023-10-26 01:10:38 +00:00
// Create our depth buffer.
glGenTextures ( 1 , & internal3d . depth ) ;
glBindTexture ( texture_target , internal3d . depth ) ;
if ( use_multiview ) {
glTexImage3D ( texture_target , 0 , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , view_count , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , nullptr ) ;
} else {
glTexImage2D ( texture_target , 0 , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , nullptr ) ;
}
glTexParameteri ( texture_target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( internal3d . depth , internal_size . x * internal_size . y * view_count * depth_format_size , " 3D depth texture " ) ;
2023-10-26 01:10:38 +00:00
// Create our internal 3D FBO.
// Note that if MSAA is used and our rt_msaa_* extensions are available, this is only used for blitting and effects.
glGenFramebuffers ( 1 , & internal3d . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , internal3d . fbo ) ;
# ifndef IOS_ENABLED
if ( use_multiview ) {
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , internal3d . color , 0 , 0 , view_count ) ;
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , internal3d . depth , 0 , 0 , view_count ) ;
} else {
# else
{
# endif
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , texture_target , internal3d . color , 0 ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , texture_target , internal3d . depth , 0 ) ;
}
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_clear_intermediate_buffers ( ) ;
WARN_PRINT ( " Could not create 3D buffers, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
}
glBindTexture ( texture_target , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
}
if ( msaa3d . mode ! = RS : : VIEWPORT_MSAA_DISABLED ) {
// Setup MSAA.
const GLsizei samples [ ] = { 1 , 2 , 4 , 8 } ;
msaa3d . samples = samples [ msaa3d . mode ] ;
// Constrain by limits of OpenGL driver.
if ( msaa3d . samples > config - > msaa_max_samples ) {
msaa3d . samples = config - > msaa_max_samples ;
}
if ( ! use_multiview & & ! config - > rt_msaa_supported ) {
// Render to texture extensions not supported? fall back to MSAA framebuffer through GL_EXT_framebuffer_multisample.
// Note, if 2D MSAA matches 3D MSAA and we're not scaling, it would be ideal if we reuse our 2D MSAA buffer here.
// We can't however because we don't trigger a change in configuration if 2D MSAA changes.
// We'll accept the overhead in this situation.
msaa3d . needs_resolve = true ;
msaa3d . check_fbo_cache = false ;
// Create our color buffer.
glGenRenderbuffers ( 1 , & msaa3d . color ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , msaa3d . color ) ;
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa3d . samples , color_internal_format , internal_size . x , internal_size . y ) ;
GLES3 : : Utilities : : get_singleton ( ) - > render_buffer_allocated_data ( msaa3d . color , internal_size . x * internal_size . y * view_count * 4 * msaa3d . samples , " MSAA 3D color render buffer " ) ;
// Create our depth buffer.
glGenRenderbuffers ( 1 , & msaa3d . depth ) ;
glBindRenderbuffer ( GL_RENDERBUFFER , msaa3d . depth ) ;
glRenderbufferStorageMultisample ( GL_RENDERBUFFER , msaa3d . samples , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y ) ;
GLES3 : : Utilities : : get_singleton ( ) - > render_buffer_allocated_data ( msaa3d . depth , internal_size . x * internal_size . y * view_count * 3 * msaa3d . samples , " MSAA 3D depth render buffer " ) ;
// Create our MSAA 3D FBO.
glGenFramebuffers ( 1 , & msaa3d . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , msaa3d . fbo ) ;
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_RENDERBUFFER , msaa3d . color ) ;
glFramebufferRenderbuffer ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , GL_RENDERBUFFER , msaa3d . depth ) ;
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_clear_msaa3d_buffers ( ) ;
2024-01-19 05:14:36 +00:00
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
2023-10-26 01:10:38 +00:00
WARN_PRINT ( " Could not create 3D MSAA buffers, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
}
glBindRenderbuffer ( GL_RENDERBUFFER , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
# if !defined(IOS_ENABLED) && !defined(WEB_ENABLED)
} else if ( use_multiview & & ! config - > rt_msaa_multiview_supported ) {
// Render to texture extensions not supported? fall back to MSAA textures through GL_EXT_multiview_texture_multisample.
msaa3d . needs_resolve = true ;
msaa3d . check_fbo_cache = false ;
// Create our color buffer.
glGenTextures ( 1 , & msaa3d . color ) ;
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . color ) ;
# ifdef ANDROID_ENABLED
glTexStorage3DMultisample ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . samples , color_internal_format , internal_size . x , internal_size . y , view_count , GL_TRUE ) ;
# else
glTexImage3DMultisample ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . samples , color_internal_format , internal_size . x , internal_size . y , view_count , GL_TRUE ) ;
# endif
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( msaa3d . color , internal_size . x * internal_size . y * view_count * color_format_size * msaa3d . samples , " MSAA 3D color texture " ) ;
2023-10-26 01:10:38 +00:00
// Create our depth buffer.
glGenTextures ( 1 , & msaa3d . depth ) ;
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . depth ) ;
# ifdef ANDROID_ENABLED
glTexStorage3DMultisample ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . samples , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , view_count , GL_TRUE ) ;
# else
glTexImage3DMultisample ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , msaa3d . samples , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , view_count , GL_TRUE ) ;
# endif
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( msaa3d . depth , internal_size . x * internal_size . y * view_count * depth_format_size * msaa3d . samples , " MSAA 3D depth texture " ) ;
2023-10-26 01:10:38 +00:00
// Create our MSAA 3D FBO.
glGenFramebuffers ( 1 , & msaa3d . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , msaa3d . fbo ) ;
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , msaa3d . color , 0 , 0 , view_count ) ;
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , msaa3d . depth , 0 , 0 , view_count ) ;
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_clear_msaa3d_buffers ( ) ;
2024-01-19 05:14:36 +00:00
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
2023-10-26 01:10:38 +00:00
WARN_PRINT ( " Could not create 3D MSAA buffers, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
}
glBindTexture ( GL_TEXTURE_2D_MULTISAMPLE_ARRAY , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
# endif
# if defined(ANDROID_ENABLED) || defined(WEB_ENABLED) // Only supported on OpenGLES!
} else if ( ! use_internal_buffer ) {
// We are going to render directly into our render target textures,
// these can change from frame to frame as we cycle through swapchains,
// hence we'll use our FBO cache here.
msaa3d . needs_resolve = false ;
msaa3d . check_fbo_cache = true ;
} else if ( use_internal_buffer ) {
// We can combine MSAA and scaling/effects.
msaa3d . needs_resolve = false ;
msaa3d . check_fbo_cache = false ;
// We render to our internal textures, MSAA is only done in tile memory only.
// On mobile this means MSAA never leaves tile memory = efficiency!
glGenFramebuffers ( 1 , & msaa3d . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , msaa3d . fbo ) ;
2023-11-08 20:54:29 +00:00
_rt_attach_textures ( internal3d . color , internal3d . depth , msaa3d . samples , view_count ) ;
2023-10-26 01:10:38 +00:00
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_clear_msaa3d_buffers ( ) ;
2024-01-19 05:14:36 +00:00
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
2023-10-26 01:10:38 +00:00
WARN_PRINT ( " Could not create 3D MSAA framebuffer, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
}
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
# endif
} else {
// HUH? how did we get here?
WARN_PRINT_ONCE ( " MSAA is not supported on this device. " ) ;
msaa3d . mode = RS : : VIEWPORT_MSAA_DISABLED ;
msaa3d . samples = 1 ;
msaa3d . check_fbo_cache = false ;
}
} else {
msaa3d . samples = 1 ;
msaa3d . check_fbo_cache = false ;
}
}
void RenderSceneBuffersGLES3 : : _clear_msaa3d_buffers ( ) {
for ( const FBDEF & cached_fbo : msaa3d . cached_fbos ) {
GLuint fbo = cached_fbo . fbo ;
glDeleteFramebuffers ( 1 , & fbo ) ;
}
msaa3d . cached_fbos . clear ( ) ;
if ( msaa3d . fbo ) {
glDeleteFramebuffers ( 1 , & msaa3d . fbo ) ;
msaa3d . fbo = 0 ;
}
if ( msaa3d . color ! = 0 ) {
if ( view_count = = 1 ) {
GLES3 : : Utilities : : get_singleton ( ) - > render_buffer_free_data ( msaa3d . color ) ;
} else {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( msaa3d . color ) ;
}
msaa3d . color = 0 ;
}
if ( msaa3d . depth ! = 0 ) {
if ( view_count = = 1 ) {
GLES3 : : Utilities : : get_singleton ( ) - > render_buffer_free_data ( msaa3d . depth ) ;
} else {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( msaa3d . depth ) ;
}
msaa3d . depth = 0 ;
}
}
void RenderSceneBuffersGLES3 : : _clear_intermediate_buffers ( ) {
if ( internal3d . fbo ) {
glDeleteFramebuffers ( 1 , & internal3d . fbo ) ;
internal3d . fbo = 0 ;
}
if ( internal3d . color ! = 0 ) {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( internal3d . color ) ;
internal3d . color = 0 ;
}
if ( internal3d . depth ! = 0 ) {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( internal3d . depth ) ;
internal3d . depth = 0 ;
}
}
void RenderSceneBuffersGLES3 : : check_backbuffer ( bool p_need_color , bool p_need_depth ) {
GLES3 : : TextureStorage * texture_storage = GLES3 : : TextureStorage : : get_singleton ( ) ;
// Setup our back buffer
if ( backbuffer3d . fbo = = 0 ) {
glGenFramebuffers ( 1 , & backbuffer3d . fbo ) ;
}
glBindFramebuffer ( GL_FRAMEBUFFER , backbuffer3d . fbo ) ;
bool use_multiview = view_count > 1 & & GLES3 : : Config : : get_singleton ( ) - > multiview_supported ;
GLenum texture_target = use_multiview ? GL_TEXTURE_2D_ARRAY : GL_TEXTURE_2D ;
2024-01-19 05:14:36 +00:00
uint32_t depth_format_size = 3 ;
2023-10-26 01:10:38 +00:00
if ( backbuffer3d . color = = 0 & & p_need_color ) {
glGenTextures ( 1 , & backbuffer3d . color ) ;
glBindTexture ( texture_target , backbuffer3d . color ) ;
if ( use_multiview ) {
glTexImage3D ( texture_target , 0 , color_internal_format , internal_size . x , internal_size . y , view_count , 0 , color_format , color_type , nullptr ) ;
} else {
glTexImage2D ( texture_target , 0 , color_internal_format , internal_size . x , internal_size . y , 0 , color_format , color_type , nullptr ) ;
}
glTexParameteri ( texture_target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( backbuffer3d . color , internal_size . x * internal_size . y * view_count * color_format_size , " 3D Back buffer color texture " ) ;
2023-10-26 01:10:38 +00:00
# ifndef IOS_ENABLED
if ( use_multiview ) {
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , backbuffer3d . color , 0 , 0 , view_count ) ;
} else {
# else
{
# endif
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , texture_target , backbuffer3d . color , 0 ) ;
}
}
if ( backbuffer3d . depth = = 0 & & p_need_depth ) {
glGenTextures ( 1 , & backbuffer3d . depth ) ;
glBindTexture ( texture_target , backbuffer3d . depth ) ;
if ( use_multiview ) {
glTexImage3D ( texture_target , 0 , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , view_count , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , nullptr ) ;
} else {
glTexImage2D ( texture_target , 0 , GL_DEPTH_COMPONENT24 , internal_size . x , internal_size . y , 0 , GL_DEPTH_COMPONENT , GL_UNSIGNED_INT , nullptr ) ;
}
glTexParameteri ( texture_target , GL_TEXTURE_MAG_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_MIN_FILTER , GL_NEAREST ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( texture_target , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
2024-01-19 05:14:36 +00:00
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( backbuffer3d . depth , internal_size . x * internal_size . y * view_count * depth_format_size , " 3D back buffer depth texture " ) ;
2023-10-26 01:10:38 +00:00
# ifndef IOS_ENABLED
if ( use_multiview ) {
glFramebufferTextureMultiviewOVR ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , backbuffer3d . depth , 0 , 0 , view_count ) ;
} else {
# else
{
# endif
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT , texture_target , backbuffer3d . depth , 0 ) ;
}
}
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
_clear_back_buffers ( ) ;
WARN_PRINT ( " Could not create 3D back buffers, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
}
glBindTexture ( texture_target , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
}
void RenderSceneBuffersGLES3 : : _clear_back_buffers ( ) {
if ( backbuffer3d . fbo ) {
glDeleteFramebuffers ( 1 , & backbuffer3d . fbo ) ;
backbuffer3d . fbo = 0 ;
}
if ( backbuffer3d . color ! = 0 ) {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( backbuffer3d . color ) ;
backbuffer3d . color = 0 ;
}
if ( backbuffer3d . depth ! = 0 ) {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( backbuffer3d . depth ) ;
backbuffer3d . depth = 0 ;
}
2022-08-04 08:40:39 +00:00
}
2024-01-19 05:14:36 +00:00
void RenderSceneBuffersGLES3 : : set_glow_enabled ( bool p_glow_enabled ) {
if ( glow . glow_enabled ! = p_glow_enabled ) {
glow . glow_enabled = p_glow_enabled ;
// Clear our main buffers, this can impact them.
_clear_msaa3d_buffers ( ) ;
_clear_intermediate_buffers ( ) ;
}
}
void RenderSceneBuffersGLES3 : : check_glow_buffers ( ) {
if ( glow . levels [ 0 ] . color ! = 0 ) {
// already have these setup..
return ;
}
GLES3 : : TextureStorage * texture_storage = GLES3 : : TextureStorage : : get_singleton ( ) ;
Size2i level_size = internal_size ;
for ( int i = 0 ; i < 4 ; i + + ) {
level_size . x = MAX ( level_size . x > > 1 , 4 ) ;
level_size . y = MAX ( level_size . y > > 1 , 4 ) ;
glow . levels [ i ] . size = level_size ;
// Create our texture
glGenTextures ( 1 , & glow . levels [ i ] . color ) ;
glActiveTexture ( GL_TEXTURE0 ) ;
glBindTexture ( GL_TEXTURE_2D , glow . levels [ i ] . color ) ;
glTexImage2D ( GL_TEXTURE_2D , 0 , color_internal_format , level_size . x , level_size . y , 0 , color_format , color_type , nullptr ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_BASE_LEVEL , 0 ) ;
glTexParameteri ( GL_TEXTURE_2D , GL_TEXTURE_MAX_LEVEL , 0 ) ;
GLES3 : : Utilities : : get_singleton ( ) - > texture_allocated_data ( glow . levels [ i ] . color , level_size . x * level_size . y * color_format_size , String ( " Glow buffer " ) + String : : num_int64 ( i ) ) ;
// Create our FBO
glGenFramebuffers ( 1 , & glow . levels [ i ] . fbo ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , glow . levels [ i ] . fbo ) ;
glFramebufferTexture2D ( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 , GL_TEXTURE_2D , glow . levels [ i ] . color , 0 ) ;
GLenum status = glCheckFramebufferStatus ( GL_FRAMEBUFFER ) ;
if ( status ! = GL_FRAMEBUFFER_COMPLETE ) {
WARN_PRINT ( " Could not create glow buffers, status: " + texture_storage - > get_framebuffer_error ( status ) ) ;
_clear_glow_buffers ( ) ;
break ;
}
}
glBindTexture ( GL_TEXTURE_2D , 0 ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , 0 ) ;
}
void RenderSceneBuffersGLES3 : : _clear_glow_buffers ( ) {
for ( int i = 0 ; i < 4 ; i + + ) {
if ( glow . levels [ i ] . fbo ! = 0 ) {
glDeleteFramebuffers ( 1 , & glow . levels [ i ] . fbo ) ;
glow . levels [ i ] . fbo = 0 ;
}
if ( glow . levels [ i ] . color ! = 0 ) {
GLES3 : : Utilities : : get_singleton ( ) - > texture_free_data ( glow . levels [ i ] . color ) ;
glow . levels [ i ] . color = 0 ;
}
}
}
2022-08-04 08:40:39 +00:00
void RenderSceneBuffersGLES3 : : free_render_buffer_data ( ) {
2023-10-26 01:10:38 +00:00
_clear_msaa3d_buffers ( ) ;
_clear_intermediate_buffers ( ) ;
_clear_back_buffers ( ) ;
2024-01-19 05:14:36 +00:00
_clear_glow_buffers ( ) ;
2023-10-26 01:10:38 +00:00
}
GLuint RenderSceneBuffersGLES3 : : get_render_fbo ( ) {
2023-11-08 20:54:29 +00:00
GLES3 : : TextureStorage * texture_storage = GLES3 : : TextureStorage : : get_singleton ( ) ;
GLuint rt_fbo = 0 ;
2023-10-26 01:10:38 +00:00
2024-01-19 05:14:36 +00:00
_check_render_buffers ( ) ;
2023-11-08 20:54:29 +00:00
if ( msaa3d . check_fbo_cache ) {
2023-10-26 01:10:38 +00:00
GLuint color = texture_storage - > render_target_get_color ( render_target ) ;
GLuint depth = texture_storage - > render_target_get_depth ( render_target ) ;
2023-11-08 20:54:29 +00:00
rt_fbo = _rt_get_cached_fbo ( color , depth , msaa3d . samples , view_count ) ;
2024-01-19 05:14:36 +00:00
if ( rt_fbo = = 0 ) {
// Somehow couldn't obtain this? Just render without MSAA.
rt_fbo = texture_storage - > render_target_get_fbo ( render_target ) ;
}
2023-10-26 01:10:38 +00:00
} else if ( msaa3d . fbo ! = 0 ) {
// We have an MSAA fbo, render to our MSAA buffer
return msaa3d . fbo ;
} else if ( internal3d . fbo ! = 0 ) {
// We have an internal buffer, render to our internal buffer!
return internal3d . fbo ;
} else {
2023-11-08 20:54:29 +00:00
rt_fbo = texture_storage - > render_target_get_fbo ( render_target ) ;
}
2023-10-26 01:10:38 +00:00
2023-11-08 20:54:29 +00:00
if ( texture_storage - > render_target_is_reattach_textures ( render_target ) ) {
GLuint color = texture_storage - > render_target_get_color ( render_target ) ;
GLuint depth = texture_storage - > render_target_get_depth ( render_target ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , rt_fbo ) ;
_rt_attach_textures ( color , depth , msaa3d . samples , view_count ) ;
glBindFramebuffer ( GL_FRAMEBUFFER , texture_storage - > system_fbo ) ;
2023-10-26 01:10:38 +00:00
}
2023-11-08 20:54:29 +00:00
return rt_fbo ;
2022-08-04 08:40:39 +00:00
}
# endif // GLES3_ENABLED