2023-01-05 13:25:55 +01:00
/**************************************************************************/
/* effects_rd.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. */
/**************************************************************************/
2019-11-05 12:01:00 +01:00
2020-12-04 19:26:24 +01:00
# include "effects_rd.h"
2020-03-28 13:29:29 +01:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2020-12-08 06:37:09 +01:00
# include "core/math/math_defs.h"
2020-01-16 01:23:21 +01:00
# include "core/os/os.h"
2020-03-28 13:29:29 +01:00
2021-05-07 15:19:04 +02:00
# include "servers/rendering/renderer_rd/renderer_compositor_rd.h"
2020-03-28 13:29:29 +01:00
# include "thirdparty/misc/cubemap_coeffs.h"
2019-07-27 15:23:24 +02:00
2021-07-27 15:33:47 +02:00
bool EffectsRD : : get_prefer_raster_effects ( ) {
return prefer_raster_effects ;
}
2020-12-04 19:26:24 +01:00
RID EffectsRD : : _get_uniform_set_from_image ( RID p_image ) {
2020-01-12 02:26:52 +01:00
if ( image_to_uniform_set_cache . has ( p_image ) ) {
RID uniform_set = image_to_uniform_set_cache [ p_image ] ;
if ( RD : : get_singleton ( ) - > uniform_set_is_valid ( uniform_set ) ) {
return uniform_set ;
}
}
Vector < RD : : Uniform > uniforms ;
RD : : Uniform u ;
2020-10-17 03:19:21 +02:00
u . uniform_type = RD : : UNIFORM_TYPE_IMAGE ;
2020-01-12 02:26:52 +01:00
u . binding = 0 ;
2022-03-06 12:57:09 +01:00
u . append_id ( p_image ) ;
2020-01-12 02:26:52 +01:00
uniforms . push_back ( u ) ;
//any thing with the same configuration (one texture in binding 0 for set 0), is good
2022-12-23 13:41:44 +01:00
RID uniform_set = RD : : get_singleton ( ) - > uniform_set_create ( uniforms , roughness_limiter . shader . version_get_shader ( roughness_limiter . shader_version , 0 ) , 1 ) ;
2020-01-12 02:26:52 +01:00
image_to_uniform_set_cache [ p_image ] = uniform_set ;
return uniform_set ;
}
2020-12-04 19:26:24 +01:00
RID EffectsRD : : _get_compute_uniform_set_from_texture ( RID p_texture , bool p_use_mipmaps ) {
2020-01-12 02:26:52 +01:00
if ( texture_to_compute_uniform_set_cache . has ( p_texture ) ) {
RID uniform_set = texture_to_compute_uniform_set_cache [ p_texture ] ;
if ( RD : : get_singleton ( ) - > uniform_set_is_valid ( uniform_set ) ) {
return uniform_set ;
}
}
Vector < RD : : Uniform > uniforms ;
RD : : Uniform u ;
2020-10-17 03:19:21 +02:00
u . uniform_type = RD : : UNIFORM_TYPE_SAMPLER_WITH_TEXTURE ;
2020-01-12 02:26:52 +01:00
u . binding = 0 ;
2022-03-06 12:57:09 +01:00
u . append_id ( p_use_mipmaps ? default_mipmap_sampler : default_sampler ) ;
u . append_id ( p_texture ) ;
2020-01-12 02:26:52 +01:00
uniforms . push_back ( u ) ;
//any thing with the same configuration (one texture in binding 0 for set 0), is good
2022-12-23 13:41:44 +01:00
RID uniform_set = RD : : get_singleton ( ) - > uniform_set_create ( uniforms , roughness_limiter . shader . version_get_shader ( roughness_limiter . shader_version , 0 ) , 0 ) ;
2020-01-12 02:26:52 +01:00
texture_to_compute_uniform_set_cache [ p_texture ] = uniform_set ;
return uniform_set ;
}
2020-12-04 19:26:24 +01:00
void EffectsRD : : roughness_limit ( RID p_source_normal , RID p_roughness , const Size2i & p_size , float p_curve ) {
2020-01-27 00:09:40 +01:00
roughness_limiter . push_constant . screen_size [ 0 ] = p_size . x ;
roughness_limiter . push_constant . screen_size [ 1 ] = p_size . y ;
roughness_limiter . push_constant . curve = p_curve ;
RD : : ComputeListID compute_list = RD : : get_singleton ( ) - > compute_list_begin ( ) ;
RD : : get_singleton ( ) - > compute_list_bind_compute_pipeline ( compute_list , roughness_limiter . pipeline ) ;
RD : : get_singleton ( ) - > compute_list_bind_uniform_set ( compute_list , _get_compute_uniform_set_from_texture ( p_source_normal ) , 0 ) ;
RD : : get_singleton ( ) - > compute_list_bind_uniform_set ( compute_list , _get_uniform_set_from_image ( p_roughness ) , 1 ) ;
RD : : get_singleton ( ) - > compute_list_set_push_constant ( compute_list , & roughness_limiter . push_constant , sizeof ( RoughnessLimiterPushConstant ) ) ; //not used but set anyway
2021-02-02 20:51:36 +01:00
RD : : get_singleton ( ) - > compute_list_dispatch_threads ( compute_list , p_size . x , p_size . y , 1 ) ;
2020-01-27 00:09:40 +01:00
RD : : get_singleton ( ) - > compute_list_end ( ) ;
}
2020-12-04 19:26:24 +01:00
void EffectsRD : : sort_buffer ( RID p_uniform_set , int p_size ) {
2020-08-19 15:38:24 +02:00
Sort : : PushConstant push_constant ;
push_constant . total_elements = p_size ;
bool done = true ;
int numThreadGroups = ( ( p_size - 1 ) > > 9 ) + 1 ;
if ( numThreadGroups > 1 ) {
done = false ;
}
RD : : ComputeListID compute_list = RD : : get_singleton ( ) - > compute_list_begin ( ) ;
RD : : get_singleton ( ) - > compute_list_bind_compute_pipeline ( compute_list , sort . pipelines [ SORT_MODE_BLOCK ] ) ;
RD : : get_singleton ( ) - > compute_list_bind_uniform_set ( compute_list , p_uniform_set , 1 ) ;
RD : : get_singleton ( ) - > compute_list_set_push_constant ( compute_list , & push_constant , sizeof ( Sort : : PushConstant ) ) ;
RD : : get_singleton ( ) - > compute_list_dispatch ( compute_list , numThreadGroups , 1 , 1 ) ;
int presorted = 512 ;
while ( ! done ) {
RD : : get_singleton ( ) - > compute_list_add_barrier ( compute_list ) ;
done = true ;
RD : : get_singleton ( ) - > compute_list_bind_compute_pipeline ( compute_list , sort . pipelines [ SORT_MODE_STEP ] ) ;
numThreadGroups = 0 ;
if ( p_size > presorted ) {
if ( p_size > presorted * 2 ) {
done = false ;
}
int pow2 = presorted ;
while ( pow2 < p_size ) {
pow2 * = 2 ;
}
numThreadGroups = pow2 > > 9 ;
}
unsigned int nMergeSize = presorted * 2 ;
for ( unsigned int nMergeSubSize = nMergeSize > > 1 ; nMergeSubSize > 256 ; nMergeSubSize = nMergeSubSize > > 1 ) {
push_constant . job_params [ 0 ] = nMergeSubSize ;
if ( nMergeSubSize = = nMergeSize > > 1 ) {
push_constant . job_params [ 1 ] = ( 2 * nMergeSubSize - 1 ) ;
push_constant . job_params [ 2 ] = - 1 ;
} else {
push_constant . job_params [ 1 ] = nMergeSubSize ;
push_constant . job_params [ 2 ] = 1 ;
}
push_constant . job_params [ 3 ] = 0 ;
RD : : get_singleton ( ) - > compute_list_set_push_constant ( compute_list , & push_constant , sizeof ( Sort : : PushConstant ) ) ;
RD : : get_singleton ( ) - > compute_list_dispatch ( compute_list , numThreadGroups , 1 , 1 ) ;
RD : : get_singleton ( ) - > compute_list_add_barrier ( compute_list ) ;
}
RD : : get_singleton ( ) - > compute_list_bind_compute_pipeline ( compute_list , sort . pipelines [ SORT_MODE_INNER ] ) ;
RD : : get_singleton ( ) - > compute_list_set_push_constant ( compute_list , & push_constant , sizeof ( Sort : : PushConstant ) ) ;
RD : : get_singleton ( ) - > compute_list_dispatch ( compute_list , numThreadGroups , 1 , 1 ) ;
presorted * = 2 ;
}
RD : : get_singleton ( ) - > compute_list_end ( ) ;
}
2021-07-20 13:40:16 +02:00
EffectsRD : : EffectsRD ( bool p_prefer_raster_effects ) {
prefer_raster_effects = p_prefer_raster_effects ;
2021-08-16 19:51:29 +02:00
if ( ! prefer_raster_effects ) {
2020-02-21 00:27:34 +01:00
// Initialize roughness limiter
2020-01-27 00:09:40 +01:00
Vector < String > shader_modes ;
shader_modes . push_back ( " " ) ;
roughness_limiter . shader . initialize ( shader_modes ) ;
roughness_limiter . shader_version = roughness_limiter . shader . version_create ( ) ;
roughness_limiter . pipeline = RD : : get_singleton ( ) - > compute_pipeline_create ( roughness_limiter . shader . version_get_shader ( roughness_limiter . shader_version , 0 ) ) ;
}
2020-08-19 15:38:24 +02:00
{
Vector < String > sort_modes ;
sort_modes . push_back ( " \n #define MODE_SORT_BLOCK \n " ) ;
sort_modes . push_back ( " \n #define MODE_SORT_STEP \n " ) ;
sort_modes . push_back ( " \n #define MODE_SORT_INNER \n " ) ;
sort . shader . initialize ( sort_modes ) ;
sort . shader_version = sort . shader . version_create ( ) ;
for ( int i = 0 ; i < SORT_MODE_MAX ; i + + ) {
sort . pipelines [ i ] = RD : : get_singleton ( ) - > compute_pipeline_create ( sort . shader . version_get_shader ( sort . shader_version , i ) ) ;
}
}
2019-07-27 15:23:24 +02:00
RD : : SamplerState sampler ;
sampler . mag_filter = RD : : SAMPLER_FILTER_LINEAR ;
sampler . min_filter = RD : : SAMPLER_FILTER_LINEAR ;
sampler . max_lod = 0 ;
default_sampler = RD : : get_singleton ( ) - > sampler_create ( sampler ) ;
2021-01-24 07:21:54 +01:00
RD : : get_singleton ( ) - > set_resource_name ( default_sampler , " Default Linear Sampler " ) ;
2019-07-27 15:23:24 +02:00
2020-01-10 01:40:26 +01:00
sampler . min_filter = RD : : SAMPLER_FILTER_LINEAR ;
sampler . mip_filter = RD : : SAMPLER_FILTER_LINEAR ;
sampler . max_lod = 1e20 ;
default_mipmap_sampler = RD : : get_singleton ( ) - > sampler_create ( sampler ) ;
2021-01-24 07:21:54 +01:00
RD : : get_singleton ( ) - > set_resource_name ( default_mipmap_sampler , " Default MipMap Sampler " ) ;
2020-01-10 01:40:26 +01:00
2019-07-27 15:23:24 +02:00
{ //create index array for copy shaders
2020-02-17 22:06:54 +01:00
Vector < uint8_t > pv ;
2019-07-27 15:23:24 +02:00
pv . resize ( 6 * 4 ) ;
{
2020-02-17 22:06:54 +01:00
uint8_t * w = pv . ptrw ( ) ;
int * p32 = ( int * ) w ;
2019-07-27 15:23:24 +02:00
p32 [ 0 ] = 0 ;
p32 [ 1 ] = 1 ;
p32 [ 2 ] = 2 ;
p32 [ 3 ] = 0 ;
p32 [ 4 ] = 2 ;
p32 [ 5 ] = 3 ;
}
index_buffer = RD : : get_singleton ( ) - > index_buffer_create ( 6 , RenderingDevice : : INDEX_BUFFER_FORMAT_UINT32 , pv ) ;
index_array = RD : : get_singleton ( ) - > index_array_create ( index_buffer , 0 , 6 ) ;
}
}
2020-12-04 19:26:24 +01:00
EffectsRD : : ~ EffectsRD ( ) {
2019-07-29 23:19:31 +02:00
RD : : get_singleton ( ) - > free ( default_sampler ) ;
2020-02-28 00:01:49 +01:00
RD : : get_singleton ( ) - > free ( default_mipmap_sampler ) ;
2019-07-29 23:19:31 +02:00
RD : : get_singleton ( ) - > free ( index_buffer ) ; //array gets freed as dependency
2020-04-04 17:48:30 +02:00
2021-08-16 19:51:29 +02:00
if ( ! prefer_raster_effects ) {
roughness_limiter . shader . version_free ( roughness_limiter . shader_version ) ;
}
2020-10-12 09:47:12 +02:00
sort . shader . version_free ( sort . shader_version ) ;
2019-07-27 15:23:24 +02:00
}