2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* taa.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. */
/**************************************************************************/
2022-08-04 18:40:39 +10:00
# include "taa.h"
# include "servers/rendering/renderer_rd/effects/copy_effects.h"
# include "servers/rendering/renderer_rd/storage_rd/material_storage.h"
# include "servers/rendering/renderer_rd/uniform_set_cache_rd.h"
using namespace RendererRD ;
TAA : : TAA ( ) {
Vector < String > taa_modes ;
taa_modes . push_back ( " \n #define MODE_TAA_RESOLVE " ) ;
taa_shader . initialize ( taa_modes ) ;
shader_version = taa_shader . version_create ( ) ;
pipeline = RD : : get_singleton ( ) - > compute_pipeline_create ( taa_shader . version_get_shader ( shader_version , 0 ) ) ;
}
TAA : : ~ TAA ( ) {
taa_shader . version_free ( shader_version ) ;
}
void TAA : : resolve ( RID p_frame , RID p_temp , RID p_depth , RID p_velocity , RID p_prev_velocity , RID p_history , Size2 p_resolution , float p_z_near , float p_z_far ) {
UniformSetCacheRD * uniform_set_cache = UniformSetCacheRD : : get_singleton ( ) ;
ERR_FAIL_NULL ( uniform_set_cache ) ;
MaterialStorage * material_storage = MaterialStorage : : get_singleton ( ) ;
ERR_FAIL_NULL ( material_storage ) ;
RID shader = taa_shader . version_get_shader ( shader_version , 0 ) ;
ERR_FAIL_COND ( shader . is_null ( ) ) ;
RID default_sampler = material_storage - > sampler_rd_get_default ( RS : : CANVAS_ITEM_TEXTURE_FILTER_LINEAR , RS : : CANVAS_ITEM_TEXTURE_REPEAT_DISABLED ) ;
2025-11-18 12:24:09 +01:00
float base_variance = 1.1f ;
float base_variance_min = 0.75f ;
float base_variance_max = 1.00f ;
float variance_scale = 1080.0f / p_resolution . height ; // 1080p taken as baseline for calculation, as this is most commonly used resolution
2022-08-04 18:40:39 +10:00
TAAResolvePushConstant push_constant ;
memset ( & push_constant , 0 , sizeof ( TAAResolvePushConstant ) ) ;
push_constant . resolution_width = p_resolution . width ;
push_constant . resolution_height = p_resolution . height ;
2024-01-04 16:09:32 -08:00
push_constant . disocclusion_threshold = 2.5f ; // If velocity changes by less than this amount of texels we can retain the accumulation buffer.
2025-11-18 12:24:09 +01:00
push_constant . variance_dynamic = CLAMP ( base_variance * variance_scale , base_variance_min , base_variance_max ) ; // Variance dynamically scales based on resolution
2022-08-04 18:40:39 +10:00
RD : : ComputeListID compute_list = RD : : get_singleton ( ) - > compute_list_begin ( ) ;
RD : : get_singleton ( ) - > compute_list_bind_compute_pipeline ( compute_list , pipeline ) ;
RD : : Uniform u_frame_source ( RD : : UNIFORM_TYPE_IMAGE , 0 , { p_frame } ) ;
RD : : Uniform u_depth ( RD : : UNIFORM_TYPE_SAMPLER_WITH_TEXTURE , 1 , { default_sampler , p_depth } ) ;
RD : : Uniform u_velocity ( RD : : UNIFORM_TYPE_IMAGE , 2 , { p_velocity } ) ;
RD : : Uniform u_prev_velocity ( RD : : UNIFORM_TYPE_IMAGE , 3 , { p_prev_velocity } ) ;
RD : : Uniform u_history ( RD : : UNIFORM_TYPE_SAMPLER_WITH_TEXTURE , 4 , { default_sampler , p_history } ) ;
RD : : Uniform u_frame_dest ( RD : : UNIFORM_TYPE_IMAGE , 5 , { p_temp } ) ;
RD : : get_singleton ( ) - > compute_list_bind_uniform_set ( compute_list , uniform_set_cache - > get_cache ( shader , 0 , u_frame_source , u_depth , u_velocity , u_prev_velocity , u_history , u_frame_dest ) , 0 ) ;
RD : : get_singleton ( ) - > compute_list_set_push_constant ( compute_list , & push_constant , sizeof ( TAAResolvePushConstant ) ) ;
RD : : get_singleton ( ) - > compute_list_dispatch_threads ( compute_list , p_resolution . width , p_resolution . height , 1 ) ;
RD : : get_singleton ( ) - > compute_list_end ( ) ;
}
void TAA : : process ( Ref < RenderSceneBuffersRD > p_render_buffers , RD : : DataFormat p_format , float p_z_near , float p_z_far ) {
CopyEffects * copy_effects = CopyEffects : : get_singleton ( ) ;
uint32_t view_count = p_render_buffers - > get_view_count ( ) ;
Size2i internal_size = p_render_buffers - > get_internal_size ( ) ;
Size2i target_size = p_render_buffers - > get_target_size ( ) ;
bool just_allocated = false ;
if ( ! p_render_buffers - > has_texture ( SNAME ( " taa " ) , SNAME ( " history " ) ) ) {
uint32_t usage_bits = RD : : TEXTURE_USAGE_SAMPLING_BIT | RD : : TEXTURE_USAGE_STORAGE_BIT ;
p_render_buffers - > create_texture ( SNAME ( " taa " ) , SNAME ( " history " ) , p_format , usage_bits ) ;
p_render_buffers - > create_texture ( SNAME ( " taa " ) , SNAME ( " temp " ) , p_format , usage_bits ) ;
p_render_buffers - > create_texture ( SNAME ( " taa " ) , SNAME ( " prev_velocity " ) , RD : : DATA_FORMAT_R16G16_SFLOAT , usage_bits ) ;
just_allocated = true ;
}
RD : : get_singleton ( ) - > draw_command_begin_label ( " TAA " ) ;
for ( uint32_t v = 0 ; v < view_count ; v + + ) {
// Get our (cached) slices
RID internal_texture = p_render_buffers - > get_internal_texture ( v ) ;
RID velocity_buffer = p_render_buffers - > get_velocity_buffer ( false , v ) ;
RID taa_history = p_render_buffers - > get_texture_slice ( SNAME ( " taa " ) , SNAME ( " history " ) , v , 0 ) ;
RID taa_prev_velocity = p_render_buffers - > get_texture_slice ( SNAME ( " taa " ) , SNAME ( " prev_velocity " ) , v , 0 ) ;
if ( ! just_allocated ) {
RID depth_texture = p_render_buffers - > get_depth_texture ( v ) ;
RID taa_temp = p_render_buffers - > get_texture_slice ( SNAME ( " taa " ) , SNAME ( " temp " ) , v , 0 ) ;
resolve ( internal_texture , taa_temp , depth_texture , velocity_buffer , taa_prev_velocity , taa_history , Size2 ( internal_size . x , internal_size . y ) , p_z_near , p_z_far ) ;
copy_effects - > copy_to_rect ( taa_temp , internal_texture , Rect2 ( 0 , 0 , internal_size . x , internal_size . y ) ) ;
}
copy_effects - > copy_to_rect ( internal_texture , taa_history , Rect2 ( 0 , 0 , internal_size . x , internal_size . y ) ) ;
copy_effects - > copy_to_rect ( velocity_buffer , taa_prev_velocity , Rect2 ( 0 , 0 , target_size . x , target_size . y ) ) ;
}
RD : : get_singleton ( ) - > draw_command_end_label ( ) ;
}