Skip to content

Commit bf47c42

Browse files
committed
Detect possible usage of SSS and screen textures at load time to allocate needed resources at load time.
This allows us to avoid a class of pipeline compilation stutters and stutters from allocating screen textures.
1 parent 87f897a commit bf47c42

File tree

6 files changed

+104
-35
lines changed

6 files changed

+104
-35
lines changed

servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1904,24 +1904,33 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
19041904
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
19051905
}
19061906

1907-
if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi) {
1907+
// Ensure this is allocated so we don't get a stutter the first time an object with SSS appears on screen.
1908+
if (global_surface_data.sss_used) {
1909+
rb_data->ensure_specular();
1910+
}
1911+
1912+
if (global_surface_data.normal_texture_used) {
1913+
rb_data->ensure_normal_roughness_texture();
1914+
}
1915+
1916+
if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi || global_surface_data.sss_used) {
19081917
scene_shader.enable_advanced_shader_group(p_render_data->scene_data->view_count > 1);
19091918
}
19101919

19111920
// Update the global pipeline requirements with all the features found to be in use in this scene.
1912-
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) {
1921+
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || global_surface_data.normal_texture_used) {
19131922
global_pipeline_data_required.use_normal_and_roughness = true;
19141923
}
19151924

1916-
if (scene_state.used_lightmap) {
1925+
if (scene_state.used_lightmap || scene_state.lightmaps_used > 0) {
19171926
global_pipeline_data_required.use_lightmaps = true;
19181927
}
19191928

19201929
if (using_voxelgi) {
19211930
global_pipeline_data_required.use_voxelgi = true;
19221931
}
19231932

1924-
if (using_separate_specular) {
1933+
if (using_separate_specular || global_surface_data.sss_used) {
19251934
global_pipeline_data_required.use_separate_specular = true;
19261935
}
19271936

@@ -2292,18 +2301,26 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
22922301
rb->ensure_upscaled();
22932302
}
22942303

2295-
if (scene_state.used_screen_texture) {
2304+
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
22962305
RENDER_TIMESTAMP("Copy Screen Texture");
22972306

2298-
// Copy screen texture to backbuffer so we can read from it
2299-
_render_buffers_copy_screen_texture(p_render_data);
2307+
_render_buffers_ensure_screen_texture(p_render_data);
2308+
2309+
if (scene_state.used_screen_texture) {
2310+
// Copy screen texture to backbuffer so we can read from it
2311+
_render_buffers_copy_screen_texture(p_render_data);
2312+
}
23002313
}
23012314

2302-
if (scene_state.used_depth_texture) {
2315+
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
23032316
RENDER_TIMESTAMP("Copy Depth Texture");
23042317

2305-
// Copy depth texture to backbuffer so we can read from it
2306-
_render_buffers_copy_depth_texture(p_render_data);
2318+
_render_buffers_ensure_depth_texture(p_render_data);
2319+
2320+
if (scene_state.used_depth_texture) {
2321+
// Copy depth texture to backbuffer so we can read from it
2322+
_render_buffers_copy_depth_texture(p_render_data);
2323+
}
23072324
}
23082325

23092326
{
@@ -3937,18 +3954,22 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
39373954

39383955
if (p_material->shader_data->uses_sss) {
39393956
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING;
3957+
global_surface_data.sss_used = true;
39403958
}
39413959

39423960
if (p_material->shader_data->uses_screen_texture) {
39433961
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
3962+
global_surface_data.screen_texture_used = true;
39443963
}
39453964

39463965
if (p_material->shader_data->uses_depth_texture) {
39473966
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
3967+
global_surface_data.depth_texture_used = true;
39483968
}
39493969

39503970
if (p_material->shader_data->uses_normal_texture) {
39513971
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
3972+
global_surface_data.normal_texture_used = true;
39523973
}
39533974

39543975
if (ginstance->data->cast_double_sided_shadows) {

servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -629,6 +629,14 @@ class RenderForwardClustered : public RendererSceneRenderRD {
629629
void _update_dirty_geometry_instances();
630630
void _update_dirty_geometry_pipelines();
631631

632+
// Global data about the scene that can be used to pre-allocate resources without relying on culling.
633+
struct GlobalSurfaceData {
634+
bool screen_texture_used = false;
635+
bool normal_texture_used = false;
636+
bool depth_texture_used = false;
637+
bool sss_used = false;
638+
} global_surface_data;
639+
632640
/* Render List */
633641

634642
struct RenderList {

servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1180,14 +1180,22 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
11801180
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data);
11811181
}
11821182

1183-
if (scene_state.used_screen_texture) {
1184-
// Copy screen texture to backbuffer so we can read from it
1185-
_render_buffers_copy_screen_texture(p_render_data);
1183+
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
1184+
_render_buffers_ensure_screen_texture(p_render_data);
1185+
1186+
if (scene_state.used_screen_texture) {
1187+
// Copy screen texture to backbuffer so we can read from it
1188+
_render_buffers_copy_screen_texture(p_render_data);
1189+
}
11861190
}
11871191

1188-
if (scene_state.used_depth_texture) {
1189-
// Copy depth texture to backbuffer so we can read from it
1190-
_render_buffers_copy_depth_texture(p_render_data);
1192+
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
1193+
_render_buffers_ensure_depth_texture(p_render_data);
1194+
1195+
if (scene_state.used_depth_texture) {
1196+
// Copy depth texture to backbuffer so we can read from it
1197+
_render_buffers_copy_depth_texture(p_render_data);
1198+
}
11911199
}
11921200

11931201
if (render_list[RENDER_LIST_ALPHA].element_info.size() > 0) {
@@ -1893,9 +1901,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
18931901
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
18941902

18951903
if (p_render_list == RENDER_LIST_OPAQUE) {
1896-
scene_state.used_sss = false;
18971904
scene_state.used_screen_texture = false;
1898-
scene_state.used_normal_texture = false;
18991905
scene_state.used_depth_texture = false;
19001906
scene_state.used_lightmap = false;
19011907
}
@@ -2049,15 +2055,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
20492055
scene_state.used_lightmap = true;
20502056
}
20512057

2052-
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
2053-
scene_state.used_sss = true;
2054-
}
20552058
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) {
20562059
scene_state.used_screen_texture = true;
20572060
}
2058-
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) {
2059-
scene_state.used_normal_texture = true;
2060-
}
20612061
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
20622062
scene_state.used_depth_texture = true;
20632063
}
@@ -2542,10 +2542,12 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
25422542

25432543
if (p_material->shader_data->uses_screen_texture) {
25442544
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
2545+
global_surface_data.screen_texture_used = true;
25452546
}
25462547

25472548
if (p_material->shader_data->uses_depth_texture) {
25482549
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
2550+
global_surface_data.depth_texture_used = true;
25492551
}
25502552

25512553
if (p_material->shader_data->uses_normal_texture) {

servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,7 @@ class RenderForwardMobile : public RendererSceneRenderRD {
282282
RID lightmap_capture_buffer;
283283

284284
bool used_screen_texture = false;
285-
bool used_normal_texture = false;
286285
bool used_depth_texture = false;
287-
bool used_sss = false;
288286
bool used_lightmap = false;
289287

290288
struct ShadowPass {
@@ -659,6 +657,12 @@ class RenderForwardMobile : public RendererSceneRenderRD {
659657
void _update_dirty_geometry_instances();
660658
void _update_dirty_geometry_pipelines();
661659

660+
// Global data about the scene that can be used to pre-allocate resources without relying on culling.
661+
struct GlobalSurfaceData {
662+
bool screen_texture_used = false;
663+
bool depth_texture_used = false;
664+
} global_surface_data;
665+
662666
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
663667
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
664668

servers/rendering/renderer_rd/renderer_scene_render_rd.cpp

Lines changed: 41 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,32 @@ void RendererSceneRenderRD::_process_compositor_effects(RS::CompositorEffectCall
319319
}
320320
}
321321

322+
void RendererSceneRenderRD::_render_buffers_ensure_screen_texture(const RenderDataRD *p_render_data) {
323+
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
324+
ERR_FAIL_COND(rb.is_null());
325+
326+
if (!rb->has_internal_texture()) {
327+
// We're likely rendering reflection probes where we can't use our backbuffers.
328+
return;
329+
}
330+
331+
bool can_use_storage = _render_buffers_can_be_storage();
332+
Size2i size = rb->get_internal_size();
333+
334+
// When upscaling, the blur texture needs to be at the target size for post-processing to work. We prefer to use a
335+
// dedicated backbuffer copy texture instead if the blur texture is not an option so shader effects work correctly.
336+
Size2i target_size = rb->get_target_size();
337+
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
338+
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
339+
if (reuse_blur_texture) {
340+
rb->allocate_blur_textures();
341+
} else {
342+
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
343+
usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
344+
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
345+
}
346+
}
347+
322348
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
323349
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
324350
ERR_FAIL_COND(rb.is_null());
@@ -340,12 +366,8 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
340366
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
341367
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
342368
if (reuse_blur_texture) {
343-
rb->allocate_blur_textures();
344369
texture_name = RB_TEX_BLUR_0;
345370
} else {
346-
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
347-
usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
348-
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
349371
texture_name = RB_TEX_BACK_COLOR;
350372
}
351373

@@ -377,7 +399,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
377399
RD::get_singleton()->draw_command_end_label();
378400
}
379401

380-
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
402+
void RendererSceneRenderRD::_render_buffers_ensure_depth_texture(const RenderDataRD *p_render_data) {
381403
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
382404
ERR_FAIL_COND(rb.is_null());
383405

@@ -386,14 +408,24 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
386408
return;
387409
}
388410

389-
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
390-
391-
// note, this only creates our back depth texture if we haven't already created it.
411+
// Note, this only creates our back depth texture if we haven't already created it.
392412
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
393413
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
394-
usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // set this as color attachment because we're copying data into it, it's not actually used as a depth buffer
414+
usage_bits |= RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT; // Set this as color attachment because we're copying data into it, it's not actually used as a depth buffer
395415

396416
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, RD::DATA_FORMAT_R32_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1);
417+
}
418+
419+
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
420+
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
421+
ERR_FAIL_COND(rb.is_null());
422+
423+
if (!rb->has_depth_texture()) {
424+
// We're likely rendering reflection probes where we can't use our backbuffers.
425+
return;
426+
}
427+
428+
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
397429

398430
bool can_use_storage = _render_buffers_can_be_storage();
399431
Size2i size = rb->get_internal_size();

servers/rendering/renderer_rd/renderer_scene_render_rd.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,9 @@ class RendererSceneRenderRD : public RendererSceneRender {
102102
bool _compositor_effects_has_flag(const RenderDataRD *p_render_data, RS::CompositorEffectFlags p_flag, RS::CompositorEffectCallbackType p_callback_type = RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_ANY);
103103
bool _has_compositor_effect(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data);
104104
void _process_compositor_effects(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data);
105+
void _render_buffers_ensure_screen_texture(const RenderDataRD *p_render_data);
105106
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
107+
void _render_buffers_ensure_depth_texture(const RenderDataRD *p_render_data);
106108
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
107109
void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
108110
void _post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data);

0 commit comments

Comments
 (0)