2019-06-22 18:34:26 +02:00
/**************************************************************************/
2020-12-04 19:26:24 +01:00
/* renderer_compositor_rd.cpp */
2019-06-22 18:34:26 +02:00
/**************************************************************************/
/* This file is part of: */
/* GODOT ENGINE */
/* https://godotengine.org */
/**************************************************************************/
2020-02-11 14:01:43 +01:00
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
2019-06-22 18:34:26 +02:00
/* */
/* 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. */
/**************************************************************************/
2020-12-04 19:26:24 +01:00
# include "renderer_compositor_rd.h"
2019-06-11 20:43:37 +02:00
2020-11-07 23:33:38 +01:00
# include "core/config/project_settings.h"
2021-06-11 14:51:48 +02:00
# include "core/io/dir_access.h"
2020-04-29 22:34:09 +02:00
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : prepare_for_blitting_render_targets ( ) {
2019-06-24 21:13:06 +02:00
RD : : get_singleton ( ) - > prepare_screen_for_drawing ( ) ;
}
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : blit_render_targets_to_screen ( DisplayServer : : WindowID p_screen , const BlitToScreen * p_render_targets , int p_amount ) {
2019-06-16 04:45:24 +02:00
RD : : DrawListID draw_list = RD : : get_singleton ( ) - > draw_list_begin_for_screen ( p_screen ) ;
2022-02-17 12:09:17 +01:00
if ( draw_list = = RD : : INVALID_ID ) {
return ; // Window is minimized and does not have valid swapchain, skip drawing without printing errors.
}
2019-06-19 22:03:19 +02:00
2019-06-16 04:45:24 +02:00
for ( int i = 0 ; i < p_amount ; i + + ) {
2022-09-01 10:10:53 +02:00
RID rd_texture = texture_storage - > render_target_get_rd_texture ( p_render_targets [ i ] . render_target ) ;
2019-06-16 04:45:24 +02:00
ERR_CONTINUE ( rd_texture . is_null ( ) ) ;
2021-05-11 15:08:38 +02:00
2019-06-16 04:45:24 +02:00
if ( ! render_target_descriptors . has ( rd_texture ) | | ! RD : : get_singleton ( ) - > uniform_set_is_valid ( render_target_descriptors [ rd_texture ] ) ) {
Vector < RD : : Uniform > uniforms ;
RD : : Uniform u ;
2020-10-17 03:19:21 +02:00
u . uniform_type = RD : : UNIFORM_TYPE_SAMPLER_WITH_TEXTURE ;
2019-06-16 04:45:24 +02:00
u . binding = 0 ;
2022-03-06 12:57:09 +01:00
u . append_id ( blit . sampler ) ;
u . append_id ( rd_texture ) ;
2019-06-19 22:03:19 +02:00
uniforms . push_back ( u ) ;
2021-05-11 15:08:38 +02:00
RID uniform_set = RD : : get_singleton ( ) - > uniform_set_create ( uniforms , blit . shader . version_get_shader ( blit . shader_version , BLIT_MODE_NORMAL ) , 0 ) ;
2019-06-16 04:45:24 +02:00
render_target_descriptors [ rd_texture ] = uniform_set ;
}
Size2 screen_size ( RD : : get_singleton ( ) - > screen_get_width ( p_screen ) , RD : : get_singleton ( ) - > screen_get_height ( p_screen ) ) ;
2021-07-03 23:09:19 +02:00
BlitMode mode = p_render_targets [ i ] . lens_distortion . apply ? BLIT_MODE_LENS : ( p_render_targets [ i ] . multi_view . use_layer ? BLIT_MODE_USE_LAYER : BLIT_MODE_NORMAL ) ;
2021-05-11 15:08:38 +02:00
RD : : get_singleton ( ) - > draw_list_bind_render_pipeline ( draw_list , blit . pipelines [ mode ] ) ;
RD : : get_singleton ( ) - > draw_list_bind_index_array ( draw_list , blit . array ) ;
2019-06-16 04:45:24 +02:00
RD : : get_singleton ( ) - > draw_list_bind_uniform_set ( draw_list , render_target_descriptors [ rd_texture ] , 0 ) ;
2021-08-29 06:52:43 +02:00
blit . push_constant . src_rect [ 0 ] = p_render_targets [ i ] . src_rect . position . x ;
blit . push_constant . src_rect [ 1 ] = p_render_targets [ i ] . src_rect . position . y ;
blit . push_constant . src_rect [ 2 ] = p_render_targets [ i ] . src_rect . size . width ;
blit . push_constant . src_rect [ 3 ] = p_render_targets [ i ] . src_rect . size . height ;
blit . push_constant . dst_rect [ 0 ] = p_render_targets [ i ] . dst_rect . position . x / screen_size . width ;
blit . push_constant . dst_rect [ 1 ] = p_render_targets [ i ] . dst_rect . position . y / screen_size . height ;
blit . push_constant . dst_rect [ 2 ] = p_render_targets [ i ] . dst_rect . size . width / screen_size . width ;
blit . push_constant . dst_rect [ 3 ] = p_render_targets [ i ] . dst_rect . size . height / screen_size . height ;
2021-05-11 15:08:38 +02:00
blit . push_constant . layer = p_render_targets [ i ] . multi_view . layer ;
blit . push_constant . eye_center [ 0 ] = p_render_targets [ i ] . lens_distortion . eye_center . x ;
blit . push_constant . eye_center [ 1 ] = p_render_targets [ i ] . lens_distortion . eye_center . y ;
blit . push_constant . k1 = p_render_targets [ i ] . lens_distortion . k1 ;
blit . push_constant . k2 = p_render_targets [ i ] . lens_distortion . k2 ;
blit . push_constant . upscale = p_render_targets [ i ] . lens_distortion . upscale ;
blit . push_constant . aspect_ratio = p_render_targets [ i ] . lens_distortion . aspect_ratio ;
2023-08-03 14:10:01 +02:00
blit . push_constant . convert_to_srgb = texture_storage - > render_target_is_using_hdr ( p_render_targets [ i ] . render_target ) ;
2021-05-11 15:08:38 +02:00
RD : : get_singleton ( ) - > draw_list_set_push_constant ( draw_list , & blit . push_constant , sizeof ( BlitPushConstant ) ) ;
2019-06-16 04:45:24 +02:00
RD : : get_singleton ( ) - > draw_list_draw ( draw_list , true ) ;
}
2019-06-19 22:03:19 +02:00
RD : : get_singleton ( ) - > draw_list_end ( ) ;
2019-06-16 04:45:24 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : begin_frame ( double frame_step ) {
2019-07-29 20:29:43 +02:00
frame + + ;
2020-05-01 14:34:23 +02:00
delta = frame_step ;
2019-07-21 16:31:30 +02:00
time + = frame_step ;
2020-04-29 22:34:09 +02:00
double time_roll_over = GLOBAL_GET ( " rendering/limits/time/time_rollover_secs " ) ;
time = Math : : fmod ( time , time_roll_over ) ;
2019-07-21 16:31:30 +02:00
canvas - > set_time ( time ) ;
2020-01-12 02:26:52 +01:00
scene - > set_time ( time , frame_step ) ;
2019-06-16 04:45:24 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : end_frame ( bool p_swap_buffers ) {
2023-08-23 18:45:11 +02:00
if ( p_swap_buffers ) {
RD : : get_singleton ( ) - > swap_buffers ( ) ;
}
2019-06-16 04:45:24 +02:00
}
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : initialize ( ) {
2021-05-11 15:08:38 +02:00
{
// Initialize blit
Vector < String > blit_modes ;
blit_modes . push_back ( " \n " ) ;
blit_modes . push_back ( " \n #define USE_LAYER \n " ) ;
blit_modes . push_back ( " \n #define USE_LAYER \n #define APPLY_LENS_DISTORTION \n " ) ;
2021-07-03 23:09:19 +02:00
blit_modes . push_back ( " \n " ) ;
2021-05-11 15:08:38 +02:00
blit . shader . initialize ( blit_modes ) ;
blit . shader_version = blit . shader . version_create ( ) ;
for ( int i = 0 ; i < BLIT_MODE_MAX ; i + + ) {
2021-07-03 23:09:19 +02:00
blit . pipelines [ i ] = RD : : get_singleton ( ) - > render_pipeline_create ( blit . shader . version_get_shader ( blit . shader_version , i ) , RD : : get_singleton ( ) - > screen_get_framebuffer_format ( ) , RD : : INVALID_ID , RD : : RENDER_PRIMITIVE_TRIANGLES , RD : : PipelineRasterizationState ( ) , RD : : PipelineMultisampleState ( ) , RD : : PipelineDepthStencilState ( ) , i = = BLIT_MODE_NORMAL_ALPHA ? RenderingDevice : : PipelineColorBlendState : : create_blend ( ) : RenderingDevice : : PipelineColorBlendState : : create_disabled ( ) , 0 ) ;
2019-06-16 04:45:24 +02:00
}
2021-05-11 15:08:38 +02:00
//create index array for copy shader
2020-02-17 22:06:54 +01:00
Vector < uint8_t > pv ;
2023-09-04 00:59:03 +02:00
pv . resize ( 6 * 2 ) ;
2019-06-16 04:45:24 +02:00
{
2020-02-17 22:06:54 +01:00
uint8_t * w = pv . ptrw ( ) ;
2023-09-04 00:59:03 +02:00
uint16_t * p16 = ( uint16_t * ) w ;
p16 [ 0 ] = 0 ;
p16 [ 1 ] = 1 ;
p16 [ 2 ] = 2 ;
p16 [ 3 ] = 0 ;
p16 [ 4 ] = 2 ;
p16 [ 5 ] = 3 ;
2019-06-16 04:45:24 +02:00
}
2023-09-04 00:59:03 +02:00
blit . index_buffer = RD : : get_singleton ( ) - > index_buffer_create ( 6 , RenderingDevice : : INDEX_BUFFER_FORMAT_UINT16 , pv ) ;
2021-05-11 15:08:38 +02:00
blit . array = RD : : get_singleton ( ) - > index_array_create ( blit . index_buffer , 0 , 6 ) ;
2019-06-16 04:45:24 +02:00
2021-05-11 15:08:38 +02:00
blit . sampler = RD : : get_singleton ( ) - > sampler_create ( RD : : SamplerState ( ) ) ;
2019-06-16 04:45:24 +02:00
}
}
2020-12-04 19:26:24 +01:00
uint64_t RendererCompositorRD : : frame = 1 ;
2019-07-29 17:59:18 +02:00
2020-12-04 19:26:24 +01:00
void RendererCompositorRD : : finalize ( ) {
2019-06-16 04:45:24 +02:00
memdelete ( scene ) ;
memdelete ( canvas ) ;
2022-06-21 02:08:33 +02:00
memdelete ( fog ) ;
2022-04-12 13:41:50 +02:00
memdelete ( particles_storage ) ;
2022-04-09 11:34:31 +02:00
memdelete ( light_storage ) ;
2022-04-02 07:29:04 +02:00
memdelete ( mesh_storage ) ;
2022-03-21 12:25:25 +01:00
memdelete ( material_storage ) ;
2022-03-12 12:19:59 +01:00
memdelete ( texture_storage ) ;
2022-06-21 02:08:33 +02:00
memdelete ( utilities ) ;
2019-06-16 04:45:24 +02:00
//only need to erase these, the rest are erased by cascade
2021-05-11 15:08:38 +02:00
blit . shader . version_free ( blit . shader_version ) ;
RD : : get_singleton ( ) - > free ( blit . index_buffer ) ;
RD : : get_singleton ( ) - > free ( blit . sampler ) ;
2019-06-16 04:45:24 +02:00
}
2022-01-19 16:09:52 +01:00
void RendererCompositorRD : : set_boot_image ( const Ref < Image > & p_image , const Color & p_color , bool p_scale , bool p_use_filter ) {
2022-09-30 03:55:32 +02:00
if ( p_image . is_null ( ) | | p_image - > is_empty ( ) ) {
return ;
}
2021-07-03 23:09:19 +02:00
RD : : get_singleton ( ) - > prepare_screen_for_drawing ( ) ;
2022-03-12 12:19:59 +01:00
RID texture = texture_storage - > texture_allocate ( ) ;
texture_storage - > texture_2d_initialize ( texture , p_image ) ;
2023-08-03 14:10:01 +02:00
RID rd_texture = texture_storage - > texture_get_rd_texture ( texture , false ) ;
2021-07-03 23:09:19 +02:00
2022-12-16 22:42:03 +01:00
RD : : SamplerState sampler_state ;
sampler_state . min_filter = p_use_filter ? RD : : SAMPLER_FILTER_LINEAR : RD : : SAMPLER_FILTER_NEAREST ;
sampler_state . mag_filter = p_use_filter ? RD : : SAMPLER_FILTER_LINEAR : RD : : SAMPLER_FILTER_NEAREST ;
sampler_state . max_lod = 0 ;
RID sampler = RD : : get_singleton ( ) - > sampler_create ( sampler_state ) ;
2021-07-03 23:09:19 +02:00
RID uset ;
{
Vector < RD : : Uniform > uniforms ;
RD : : Uniform u ;
u . uniform_type = RD : : UNIFORM_TYPE_SAMPLER_WITH_TEXTURE ;
u . binding = 0 ;
2022-12-16 22:42:03 +01:00
u . append_id ( sampler ) ;
2022-03-06 12:57:09 +01:00
u . append_id ( rd_texture ) ;
2021-07-03 23:09:19 +02:00
uniforms . push_back ( u ) ;
uset = RD : : get_singleton ( ) - > uniform_set_create ( uniforms , blit . shader . version_get_shader ( blit . shader_version , BLIT_MODE_NORMAL ) , 0 ) ;
}
Size2 window_size = DisplayServer : : get_singleton ( ) - > window_get_size ( ) ;
Rect2 imgrect ( 0 , 0 , p_image - > get_width ( ) , p_image - > get_height ( ) ) ;
Rect2 screenrect ;
2022-01-19 16:09:52 +01:00
if ( p_scale ) {
if ( window_size . width > window_size . height ) {
//scale horizontally
2021-07-03 23:09:19 +02:00
screenrect . size . y = window_size . height ;
screenrect . size . x = imgrect . size . x * window_size . height / imgrect . size . y ;
screenrect . position . x = ( window_size . width - screenrect . size . x ) / 2 ;
2022-01-19 16:09:52 +01:00
} else {
//scale vertically
2021-07-03 23:09:19 +02:00
screenrect . size . x = window_size . width ;
2022-01-19 16:09:52 +01:00
screenrect . size . y = imgrect . size . y * window_size . width / imgrect . size . x ;
screenrect . position . y = ( window_size . height - screenrect . size . y ) / 2 ;
}
} else {
screenrect = imgrect ;
screenrect . position + = ( ( window_size - screenrect . size ) / 2.0 ) . floor ( ) ;
2021-07-03 23:09:19 +02:00
}
screenrect . position / = window_size ;
screenrect . size / = window_size ;
RD : : DrawListID draw_list = RD : : get_singleton ( ) - > draw_list_begin_for_screen ( DisplayServer : : MAIN_WINDOW_ID , p_color ) ;
RD : : get_singleton ( ) - > draw_list_bind_render_pipeline ( draw_list , blit . pipelines [ BLIT_MODE_NORMAL_ALPHA ] ) ;
RD : : get_singleton ( ) - > draw_list_bind_index_array ( draw_list , blit . array ) ;
RD : : get_singleton ( ) - > draw_list_bind_uniform_set ( draw_list , uset , 0 ) ;
2021-08-29 06:52:43 +02:00
blit . push_constant . src_rect [ 0 ] = 0.0 ;
blit . push_constant . src_rect [ 1 ] = 0.0 ;
blit . push_constant . src_rect [ 2 ] = 1.0 ;
blit . push_constant . src_rect [ 3 ] = 1.0 ;
blit . push_constant . dst_rect [ 0 ] = screenrect . position . x ;
blit . push_constant . dst_rect [ 1 ] = screenrect . position . y ;
blit . push_constant . dst_rect [ 2 ] = screenrect . size . width ;
blit . push_constant . dst_rect [ 3 ] = screenrect . size . height ;
2021-07-03 23:09:19 +02:00
blit . push_constant . layer = 0 ;
blit . push_constant . eye_center [ 0 ] = 0 ;
blit . push_constant . eye_center [ 1 ] = 0 ;
blit . push_constant . k1 = 0 ;
blit . push_constant . k2 = 0 ;
blit . push_constant . upscale = 1.0 ;
blit . push_constant . aspect_ratio = 1.0 ;
2023-08-03 14:10:01 +02:00
blit . push_constant . convert_to_srgb = false ;
2021-07-03 23:09:19 +02:00
RD : : get_singleton ( ) - > draw_list_set_push_constant ( draw_list , & blit . push_constant , sizeof ( BlitPushConstant ) ) ;
RD : : get_singleton ( ) - > draw_list_draw ( draw_list , true ) ;
RD : : get_singleton ( ) - > draw_list_end ( ) ;
RD : : get_singleton ( ) - > swap_buffers ( ) ;
2022-03-12 12:19:59 +01:00
texture_storage - > texture_free ( texture ) ;
2022-12-16 22:42:03 +01:00
RD : : get_singleton ( ) - > free ( sampler ) ;
2021-07-03 23:09:19 +02:00
}
2020-12-04 19:26:24 +01:00
RendererCompositorRD * RendererCompositorRD : : singleton = nullptr ;
2020-05-01 14:34:23 +02:00
2020-12-04 19:26:24 +01:00
RendererCompositorRD : : RendererCompositorRD ( ) {
2022-03-06 12:57:09 +01:00
uniform_set_cache = memnew ( UniformSetCacheRD ) ;
2022-08-05 11:59:58 +02:00
framebuffer_cache = memnew ( FramebufferCacheRD ) ;
2022-03-06 12:57:09 +01:00
2021-05-25 02:25:11 +02:00
{
String shader_cache_dir = Engine : : get_singleton ( ) - > get_shader_cache_path ( ) ;
2021-12-09 10:42:46 +01:00
if ( shader_cache_dir . is_empty ( ) ) {
2021-05-25 02:25:11 +02:00
shader_cache_dir = " user:// " ;
}
2022-03-23 10:08:58 +01:00
Ref < DirAccess > da = DirAccess : : open ( shader_cache_dir ) ;
if ( da . is_null ( ) ) {
2021-05-25 02:25:11 +02:00
ERR_PRINT ( " Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir ) ;
} else {
Error err = da - > change_dir ( " shader_cache " ) ;
if ( err ! = OK ) {
err = da - > make_dir ( " shader_cache " ) ;
}
if ( err ! = OK ) {
ERR_PRINT ( " Can't create shader cache folder, no shader caching will happen: " + shader_cache_dir ) ;
} else {
2022-08-30 02:34:01 +02:00
shader_cache_dir = shader_cache_dir . path_join ( " shader_cache " ) ;
2021-05-25 02:25:11 +02:00
bool shader_cache_enabled = GLOBAL_GET ( " rendering/shader_compiler/shader_cache/enabled " ) ;
if ( ! Engine : : get_singleton ( ) - > is_editor_hint ( ) & & ! shader_cache_enabled ) {
shader_cache_dir = String ( ) ; //disable only if not editor
}
2021-12-09 10:42:46 +01:00
if ( ! shader_cache_dir . is_empty ( ) ) {
2021-05-25 02:25:11 +02:00
bool compress = GLOBAL_GET ( " rendering/shader_compiler/shader_cache/compress " ) ;
bool use_zstd = GLOBAL_GET ( " rendering/shader_compiler/shader_cache/use_zstd_compression " ) ;
bool strip_debug = GLOBAL_GET ( " rendering/shader_compiler/shader_cache/strip_debug " ) ;
ShaderRD : : set_shader_cache_dir ( shader_cache_dir ) ;
ShaderRD : : set_shader_cache_save_compressed ( compress ) ;
ShaderRD : : set_shader_cache_save_compressed_zstd ( use_zstd ) ;
ShaderRD : : set_shader_cache_save_debug ( ! strip_debug ) ;
}
}
}
}
2020-05-01 14:34:23 +02:00
singleton = this ;
2019-07-29 20:29:43 +02:00
2022-06-21 02:08:33 +02:00
utilities = memnew ( RendererRD : : Utilities ) ;
2022-03-12 12:19:59 +01:00
texture_storage = memnew ( RendererRD : : TextureStorage ) ;
2022-03-21 12:25:25 +01:00
material_storage = memnew ( RendererRD : : MaterialStorage ) ;
2022-04-02 07:29:04 +02:00
mesh_storage = memnew ( RendererRD : : MeshStorage ) ;
2022-04-09 11:34:31 +02:00
light_storage = memnew ( RendererRD : : LightStorage ) ;
2022-04-12 13:41:50 +02:00
particles_storage = memnew ( RendererRD : : ParticlesStorage ) ;
2022-06-21 02:08:33 +02:00
fog = memnew ( RendererRD : : Fog ) ;
canvas = memnew ( RendererCanvasRenderRD ( ) ) ;
2021-03-10 12:23:55 +01:00
2022-09-08 02:44:36 +02:00
String rendering_method = GLOBAL_GET ( " rendering/renderer/rendering_method " ) ;
2022-03-10 18:43:27 +01:00
uint64_t textures_per_stage = RD : : get_singleton ( ) - > limit_get ( RD : : LIMIT_MAX_TEXTURES_PER_SHADER_STAGE ) ;
2021-03-10 12:23:55 +01:00
2022-09-08 02:44:36 +02:00
if ( rendering_method = = " mobile " | | textures_per_stage < 48 ) {
if ( rendering_method = = " forward_plus " ) {
WARN_PRINT_ONCE ( " Platform supports less than 48 textures per stage which is less than required by the Clustered renderer. Defaulting to Mobile renderer. " ) ;
}
2023-10-31 10:58:04 +01:00
scene = memnew ( RendererSceneRenderImplementation : : RenderForwardMobile ( ) ) ;
2022-09-08 02:44:36 +02:00
} else if ( rendering_method = = " forward_plus " ) {
2022-06-21 02:08:33 +02:00
scene = memnew ( RendererSceneRenderImplementation : : RenderForwardClustered ( ) ) ;
2022-09-08 02:44:36 +02:00
} else {
2023-10-31 10:58:04 +01:00
// Fall back to our high end renderer.
ERR_PRINT ( vformat ( " Cannot instantiate RenderingDevice-based renderer with renderer type '%s'. Defaulting to Forward+ renderer. " , rendering_method ) ) ;
scene = memnew ( RendererSceneRenderImplementation : : RenderForwardClustered ( ) ) ;
2021-03-10 12:23:55 +01:00
}
2021-07-20 13:40:16 +02:00
2021-08-16 19:51:29 +02:00
scene - > init ( ) ;
2019-06-11 20:43:37 +02:00
}
2021-05-25 02:25:11 +02:00
RendererCompositorRD : : ~ RendererCompositorRD ( ) {
2022-03-06 12:57:09 +01:00
memdelete ( uniform_set_cache ) ;
2022-08-05 11:59:58 +02:00
memdelete ( framebuffer_cache ) ;
2021-05-25 02:25:11 +02:00
ShaderRD : : set_shader_cache_dir ( String ( ) ) ;
}