Skip to content

Commit 06c71fb

Browse files
committed
Merge pull request #105175 from clayjohn/RD-pipeline-sss-roughness
Detect more pipeline settings at load time to avoid pipeline stutters
2 parents d534107 + bf47c42 commit 06c71fb

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
@@ -1902,24 +1902,33 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
19021902
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
19031903
}
19041904

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

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

1914-
if (scene_state.used_lightmap) {
1923+
if (scene_state.used_lightmap || scene_state.lightmaps_used > 0) {
19151924
global_pipeline_data_required.use_lightmaps = true;
19161925
}
19171926

19181927
if (using_voxelgi) {
19191928
global_pipeline_data_required.use_voxelgi = true;
19201929
}
19211930

1922-
if (using_separate_specular) {
1931+
if (using_separate_specular || global_surface_data.sss_used) {
19231932
global_pipeline_data_required.use_separate_specular = true;
19241933
}
19251934

@@ -2290,18 +2299,26 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
22902299
rb->ensure_upscaled();
22912300
}
22922301

2293-
if (scene_state.used_screen_texture) {
2302+
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
22942303
RENDER_TIMESTAMP("Copy Screen Texture");
22952304

2296-
// Copy screen texture to backbuffer so we can read from it
2297-
_render_buffers_copy_screen_texture(p_render_data);
2305+
_render_buffers_ensure_screen_texture(p_render_data);
2306+
2307+
if (scene_state.used_screen_texture) {
2308+
// Copy screen texture to backbuffer so we can read from it
2309+
_render_buffers_copy_screen_texture(p_render_data);
2310+
}
22982311
}
22992312

2300-
if (scene_state.used_depth_texture) {
2313+
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
23012314
RENDER_TIMESTAMP("Copy Depth Texture");
23022315

2303-
// Copy depth texture to backbuffer so we can read from it
2304-
_render_buffers_copy_depth_texture(p_render_data);
2316+
_render_buffers_ensure_depth_texture(p_render_data);
2317+
2318+
if (scene_state.used_depth_texture) {
2319+
// Copy depth texture to backbuffer so we can read from it
2320+
_render_buffers_copy_depth_texture(p_render_data);
2321+
}
23052322
}
23062323

23072324
{
@@ -3935,18 +3952,22 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
39353952

39363953
if (p_material->shader_data->uses_sss) {
39373954
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING;
3955+
global_surface_data.sss_used = true;
39383956
}
39393957

39403958
if (p_material->shader_data->uses_screen_texture) {
39413959
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
3960+
global_surface_data.screen_texture_used = true;
39423961
}
39433962

39443963
if (p_material->shader_data->uses_depth_texture) {
39453964
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
3965+
global_surface_data.depth_texture_used = true;
39463966
}
39473967

39483968
if (p_material->shader_data->uses_normal_texture) {
39493969
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
3970+
global_surface_data.normal_texture_used = true;
39503971
}
39513972

39523973
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
@@ -1174,14 +1174,22 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
11741174
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data);
11751175
}
11761176

1177-
if (scene_state.used_screen_texture) {
1178-
// Copy screen texture to backbuffer so we can read from it
1179-
_render_buffers_copy_screen_texture(p_render_data);
1177+
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
1178+
_render_buffers_ensure_screen_texture(p_render_data);
1179+
1180+
if (scene_state.used_screen_texture) {
1181+
// Copy screen texture to backbuffer so we can read from it
1182+
_render_buffers_copy_screen_texture(p_render_data);
1183+
}
11801184
}
11811185

1182-
if (scene_state.used_depth_texture) {
1183-
// Copy depth texture to backbuffer so we can read from it
1184-
_render_buffers_copy_depth_texture(p_render_data);
1186+
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
1187+
_render_buffers_ensure_depth_texture(p_render_data);
1188+
1189+
if (scene_state.used_depth_texture) {
1190+
// Copy depth texture to backbuffer so we can read from it
1191+
_render_buffers_copy_depth_texture(p_render_data);
1192+
}
11851193
}
11861194

11871195
if (render_list[RENDER_LIST_ALPHA].element_info.size() > 0) {
@@ -1887,9 +1895,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
18871895
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
18881896

18891897
if (p_render_list == RENDER_LIST_OPAQUE) {
1890-
scene_state.used_sss = false;
18911898
scene_state.used_screen_texture = false;
1892-
scene_state.used_normal_texture = false;
18931899
scene_state.used_depth_texture = false;
18941900
scene_state.used_lightmap = false;
18951901
}
@@ -2043,15 +2049,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
20432049
scene_state.used_lightmap = true;
20442050
}
20452051

2046-
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
2047-
scene_state.used_sss = true;
2048-
}
20492052
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) {
20502053
scene_state.used_screen_texture = true;
20512054
}
2052-
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) {
2053-
scene_state.used_normal_texture = true;
2054-
}
20552055
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
20562056
scene_state.used_depth_texture = true;
20572057
}
@@ -2536,10 +2536,12 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
25362536

25372537
if (p_material->shader_data->uses_screen_texture) {
25382538
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
2539+
global_surface_data.screen_texture_used = true;
25392540
}
25402541

25412542
if (p_material->shader_data->uses_depth_texture) {
25422543
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
2544+
global_surface_data.depth_texture_used = true;
25432545
}
25442546

25452547
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
@@ -315,6 +315,32 @@ void RendererSceneRenderRD::_process_compositor_effects(RS::CompositorEffectCall
315315
}
316316
}
317317

318+
void RendererSceneRenderRD::_render_buffers_ensure_screen_texture(const RenderDataRD *p_render_data) {
319+
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
320+
ERR_FAIL_COND(rb.is_null());
321+
322+
if (!rb->has_internal_texture()) {
323+
// We're likely rendering reflection probes where we can't use our backbuffers.
324+
return;
325+
}
326+
327+
bool can_use_storage = _render_buffers_can_be_storage();
328+
Size2i size = rb->get_internal_size();
329+
330+
// When upscaling, the blur texture needs to be at the target size for post-processing to work. We prefer to use a
331+
// dedicated backbuffer copy texture instead if the blur texture is not an option so shader effects work correctly.
332+
Size2i target_size = rb->get_target_size();
333+
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
334+
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
335+
if (reuse_blur_texture) {
336+
rb->allocate_blur_textures();
337+
} else {
338+
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
339+
usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
340+
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
341+
}
342+
}
343+
318344
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
319345
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
320346
ERR_FAIL_COND(rb.is_null());
@@ -336,12 +362,8 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
336362
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
337363
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
338364
if (reuse_blur_texture) {
339-
rb->allocate_blur_textures();
340365
texture_name = RB_TEX_BLUR_0;
341366
} 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);
345367
texture_name = RB_TEX_BACK_COLOR;
346368
}
347369

@@ -373,7 +395,7 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
373395
RD::get_singleton()->draw_command_end_label();
374396
}
375397

376-
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
398+
void RendererSceneRenderRD::_render_buffers_ensure_depth_texture(const RenderDataRD *p_render_data) {
377399
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
378400
ERR_FAIL_COND(rb.is_null());
379401

@@ -382,14 +404,24 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
382404
return;
383405
}
384406

385-
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
386-
387-
// note, this only creates our back depth texture if we haven't already created it.
407+
// Note, this only creates our back depth texture if we haven't already created it.
388408
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
389409
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
390-
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
410+
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
391411

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

394426
bool can_use_storage = _render_buffers_can_be_storage();
395427
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)