You've already forked godot
mirror of
https://github.com/godotengine/godot.git
synced 2025-11-05 12:10:55 +00:00
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.
This commit is contained in:
@@ -1904,16 +1904,25 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
color_framebuffer = rb_data->get_color_pass_fb(color_pass_flags);
|
||||
}
|
||||
|
||||
if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi) {
|
||||
// Ensure this is allocated so we don't get a stutter the first time an object with SSS appears on screen.
|
||||
if (global_surface_data.sss_used) {
|
||||
rb_data->ensure_specular();
|
||||
}
|
||||
|
||||
if (global_surface_data.normal_texture_used) {
|
||||
rb_data->ensure_normal_roughness_texture();
|
||||
}
|
||||
|
||||
if (using_sss || using_separate_specular || scene_state.used_lightmap || using_voxelgi || global_surface_data.sss_used) {
|
||||
scene_shader.enable_advanced_shader_group(p_render_data->scene_data->view_count > 1);
|
||||
}
|
||||
|
||||
// Update the global pipeline requirements with all the features found to be in use in this scene.
|
||||
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS) {
|
||||
if (depth_pass_mode == PASS_MODE_DEPTH_NORMAL_ROUGHNESS || global_surface_data.normal_texture_used) {
|
||||
global_pipeline_data_required.use_normal_and_roughness = true;
|
||||
}
|
||||
|
||||
if (scene_state.used_lightmap) {
|
||||
if (scene_state.used_lightmap || scene_state.lightmaps_used > 0) {
|
||||
global_pipeline_data_required.use_lightmaps = true;
|
||||
}
|
||||
|
||||
@@ -1921,7 +1930,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
global_pipeline_data_required.use_voxelgi = true;
|
||||
}
|
||||
|
||||
if (using_separate_specular) {
|
||||
if (using_separate_specular || global_surface_data.sss_used) {
|
||||
global_pipeline_data_required.use_separate_specular = true;
|
||||
}
|
||||
|
||||
@@ -2292,19 +2301,27 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co
|
||||
rb->ensure_upscaled();
|
||||
}
|
||||
|
||||
if (scene_state.used_screen_texture) {
|
||||
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
|
||||
RENDER_TIMESTAMP("Copy Screen Texture");
|
||||
|
||||
_render_buffers_ensure_screen_texture(p_render_data);
|
||||
|
||||
if (scene_state.used_screen_texture) {
|
||||
// Copy screen texture to backbuffer so we can read from it
|
||||
_render_buffers_copy_screen_texture(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (scene_state.used_depth_texture) {
|
||||
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
|
||||
RENDER_TIMESTAMP("Copy Depth Texture");
|
||||
|
||||
_render_buffers_ensure_depth_texture(p_render_data);
|
||||
|
||||
if (scene_state.used_depth_texture) {
|
||||
// Copy depth texture to backbuffer so we can read from it
|
||||
_render_buffers_copy_depth_texture(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
if (using_separate_specular) {
|
||||
@@ -3937,18 +3954,22 @@ void RenderForwardClustered::_geometry_instance_add_surface_with_material(Geomet
|
||||
|
||||
if (p_material->shader_data->uses_sss) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING;
|
||||
global_surface_data.sss_used = true;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_screen_texture) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
|
||||
global_surface_data.screen_texture_used = true;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_depth_texture) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
|
||||
global_surface_data.depth_texture_used = true;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_normal_texture) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE;
|
||||
global_surface_data.normal_texture_used = true;
|
||||
}
|
||||
|
||||
if (ginstance->data->cast_double_sided_shadows) {
|
||||
|
||||
@@ -629,6 +629,14 @@ private:
|
||||
void _update_dirty_geometry_instances();
|
||||
void _update_dirty_geometry_pipelines();
|
||||
|
||||
// Global data about the scene that can be used to pre-allocate resources without relying on culling.
|
||||
struct GlobalSurfaceData {
|
||||
bool screen_texture_used = false;
|
||||
bool normal_texture_used = false;
|
||||
bool depth_texture_used = false;
|
||||
bool sss_used = false;
|
||||
} global_surface_data;
|
||||
|
||||
/* Render List */
|
||||
|
||||
struct RenderList {
|
||||
|
||||
@@ -1180,15 +1180,23 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
|
||||
_process_compositor_effects(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data);
|
||||
}
|
||||
|
||||
if (scene_state.used_screen_texture || global_surface_data.screen_texture_used) {
|
||||
_render_buffers_ensure_screen_texture(p_render_data);
|
||||
|
||||
if (scene_state.used_screen_texture) {
|
||||
// Copy screen texture to backbuffer so we can read from it
|
||||
_render_buffers_copy_screen_texture(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
|
||||
_render_buffers_ensure_depth_texture(p_render_data);
|
||||
|
||||
if (scene_state.used_depth_texture) {
|
||||
// Copy depth texture to backbuffer so we can read from it
|
||||
_render_buffers_copy_depth_texture(p_render_data);
|
||||
}
|
||||
}
|
||||
|
||||
if (render_list[RENDER_LIST_ALPHA].element_info.size() > 0) {
|
||||
RD::get_singleton()->draw_command_begin_label("Render Transparent Pass");
|
||||
@@ -1893,9 +1901,7 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
|
||||
RendererRD::MeshStorage *mesh_storage = RendererRD::MeshStorage::get_singleton();
|
||||
|
||||
if (p_render_list == RENDER_LIST_OPAQUE) {
|
||||
scene_state.used_sss = false;
|
||||
scene_state.used_screen_texture = false;
|
||||
scene_state.used_normal_texture = false;
|
||||
scene_state.used_depth_texture = false;
|
||||
scene_state.used_lightmap = false;
|
||||
}
|
||||
@@ -2049,15 +2055,9 @@ void RenderForwardMobile::_fill_render_list(RenderListType p_render_list, const
|
||||
scene_state.used_lightmap = true;
|
||||
}
|
||||
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SUBSURFACE_SCATTERING) {
|
||||
scene_state.used_sss = true;
|
||||
}
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE) {
|
||||
scene_state.used_screen_texture = true;
|
||||
}
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_NORMAL_TEXTURE) {
|
||||
scene_state.used_normal_texture = true;
|
||||
}
|
||||
if (surf->flags & GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE) {
|
||||
scene_state.used_depth_texture = true;
|
||||
}
|
||||
@@ -2542,10 +2542,12 @@ void RenderForwardMobile::_geometry_instance_add_surface_with_material(GeometryI
|
||||
|
||||
if (p_material->shader_data->uses_screen_texture) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_SCREEN_TEXTURE;
|
||||
global_surface_data.screen_texture_used = true;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_depth_texture) {
|
||||
flags |= GeometryInstanceSurfaceDataCache::FLAG_USES_DEPTH_TEXTURE;
|
||||
global_surface_data.depth_texture_used = true;
|
||||
}
|
||||
|
||||
if (p_material->shader_data->uses_normal_texture) {
|
||||
|
||||
@@ -282,9 +282,7 @@ private:
|
||||
RID lightmap_capture_buffer;
|
||||
|
||||
bool used_screen_texture = false;
|
||||
bool used_normal_texture = false;
|
||||
bool used_depth_texture = false;
|
||||
bool used_sss = false;
|
||||
bool used_lightmap = false;
|
||||
|
||||
struct ShadowPass {
|
||||
@@ -659,6 +657,12 @@ public:
|
||||
void _update_dirty_geometry_instances();
|
||||
void _update_dirty_geometry_pipelines();
|
||||
|
||||
// Global data about the scene that can be used to pre-allocate resources without relying on culling.
|
||||
struct GlobalSurfaceData {
|
||||
bool screen_texture_used = false;
|
||||
bool depth_texture_used = false;
|
||||
} global_surface_data;
|
||||
|
||||
virtual RenderGeometryInstance *geometry_instance_create(RID p_base) override;
|
||||
virtual void geometry_instance_free(RenderGeometryInstance *p_geometry_instance) override;
|
||||
|
||||
|
||||
@@ -319,6 +319,32 @@ void RendererSceneRenderRD::_process_compositor_effects(RS::CompositorEffectCall
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_render_buffers_ensure_screen_texture(const RenderDataRD *p_render_data) {
|
||||
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
|
||||
ERR_FAIL_COND(rb.is_null());
|
||||
|
||||
if (!rb->has_internal_texture()) {
|
||||
// We're likely rendering reflection probes where we can't use our backbuffers.
|
||||
return;
|
||||
}
|
||||
|
||||
bool can_use_storage = _render_buffers_can_be_storage();
|
||||
Size2i size = rb->get_internal_size();
|
||||
|
||||
// When upscaling, the blur texture needs to be at the target size for post-processing to work. We prefer to use a
|
||||
// dedicated backbuffer copy texture instead if the blur texture is not an option so shader effects work correctly.
|
||||
Size2i target_size = rb->get_target_size();
|
||||
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
|
||||
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
|
||||
if (reuse_blur_texture) {
|
||||
rb->allocate_blur_textures();
|
||||
} else {
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
|
||||
}
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderDataRD *p_render_data) {
|
||||
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
|
||||
ERR_FAIL_COND(rb.is_null());
|
||||
@@ -340,12 +366,8 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
|
||||
bool internal_size_matches = (size.width == target_size.width) && (size.height == target_size.height);
|
||||
bool reuse_blur_texture = !rb->has_upscaled_texture() || internal_size_matches;
|
||||
if (reuse_blur_texture) {
|
||||
rb->allocate_blur_textures();
|
||||
texture_name = RB_TEX_BLUR_0;
|
||||
} else {
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT | RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
|
||||
usage_bits |= can_use_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : RD::TEXTURE_USAGE_COLOR_ATTACHMENT_BIT;
|
||||
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_COLOR, rb->get_base_data_format(), usage_bits);
|
||||
texture_name = RB_TEX_BACK_COLOR;
|
||||
}
|
||||
|
||||
@@ -377,6 +399,23 @@ void RendererSceneRenderRD::_render_buffers_copy_screen_texture(const RenderData
|
||||
RD::get_singleton()->draw_command_end_label();
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_render_buffers_ensure_depth_texture(const RenderDataRD *p_render_data) {
|
||||
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
|
||||
ERR_FAIL_COND(rb.is_null());
|
||||
|
||||
if (!rb->has_depth_texture()) {
|
||||
// We're likely rendering reflection probes where we can't use our backbuffers.
|
||||
return;
|
||||
}
|
||||
|
||||
// Note, this only creates our back depth texture if we haven't already created it.
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
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
|
||||
|
||||
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, RD::DATA_FORMAT_R32_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1);
|
||||
}
|
||||
|
||||
void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data) {
|
||||
Ref<RenderSceneBuffersRD> rb = p_render_data->render_buffers;
|
||||
ERR_FAIL_COND(rb.is_null());
|
||||
@@ -388,13 +427,6 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR
|
||||
|
||||
RD::get_singleton()->draw_command_begin_label("Copy depth texture");
|
||||
|
||||
// note, this only creates our back depth texture if we haven't already created it.
|
||||
uint32_t usage_bits = RD::TEXTURE_USAGE_SAMPLING_BIT;
|
||||
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | RD::TEXTURE_USAGE_STORAGE_BIT;
|
||||
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
|
||||
|
||||
rb->create_texture(RB_SCOPE_BUFFERS, RB_TEX_BACK_DEPTH, RD::DATA_FORMAT_R32_SFLOAT, usage_bits, RD::TEXTURE_SAMPLES_1);
|
||||
|
||||
bool can_use_storage = _render_buffers_can_be_storage();
|
||||
Size2i size = rb->get_internal_size();
|
||||
for (uint32_t v = 0; v < p_render_data->scene_data->view_count; v++) {
|
||||
|
||||
@@ -102,7 +102,9 @@ protected:
|
||||
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);
|
||||
bool _has_compositor_effect(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data);
|
||||
void _process_compositor_effects(RS::CompositorEffectCallbackType p_callback_type, const RenderDataRD *p_render_data);
|
||||
void _render_buffers_ensure_screen_texture(const RenderDataRD *p_render_data);
|
||||
void _render_buffers_copy_screen_texture(const RenderDataRD *p_render_data);
|
||||
void _render_buffers_ensure_depth_texture(const RenderDataRD *p_render_data);
|
||||
void _render_buffers_copy_depth_texture(const RenderDataRD *p_render_data);
|
||||
void _render_buffers_post_process_and_tonemap(const RenderDataRD *p_render_data);
|
||||
void _post_process_subpass(RID p_source_texture, RID p_framebuffer, const RenderDataRD *p_render_data);
|
||||
|
||||
Reference in New Issue
Block a user