From 1d9910cac4c5598eef5e349e612643184d4cb99d Mon Sep 17 00:00:00 2001 From: Skyth <19259897+blueskythlikesclouds@users.noreply.github.com> Date: Tue, 20 Jan 2026 18:17:24 +0300 Subject: [PATCH] Give every pass its own unique environment uniform buffer. --- .../render_forward_clustered.cpp | 71 ++++++++++--------- .../render_forward_clustered.h | 9 ++- 2 files changed, 45 insertions(+), 35 deletions(-) diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp index 28fe6ac5896..63d51d8356d 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -686,7 +686,7 @@ void RenderForwardClustered::_render_list_with_draw_list(RenderListParameters *p RD::get_singleton()->draw_list_end(); } -void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Size2 &p_viewport_size, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier, bool p_pancake_shadows, int p_index) { +uint32_t RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Size2 &p_viewport_size, const Color &p_default_bg_color, bool p_opaque_render_buffers, bool p_apply_alpha_multiplier, bool p_pancake_shadows) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); Ref rd = p_render_data->render_buffers; @@ -694,9 +694,12 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat RID reflection_probe_instance = p_render_data->reflection_probe.is_valid() ? light_storage->reflection_probe_instance_get_probe(p_render_data->reflection_probe) : RID(); // May do this earlier in RenderSceneRenderRD::render_scene - if (p_index >= (int)scene_state.uniform_buffers.size()) { + uint32_t uniform_buffer_index = scene_state.used_uniform_buffer_count; + ++scene_state.used_uniform_buffer_count; + + if (uniform_buffer_index >= scene_state.uniform_buffers.size()) { uint32_t from = scene_state.uniform_buffers.size(); - scene_state.uniform_buffers.resize(p_index + 1); + scene_state.uniform_buffers.resize(uniform_buffer_index + 1); for (uint32_t i = from; i < scene_state.uniform_buffers.size(); i++) { scene_state.uniform_buffers[i] = p_render_data->scene_data->create_uniform_buffer(); } @@ -704,7 +707,7 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat float luminance_multiplier = rd.is_valid() ? rd->get_luminance_multiplier() : 1.0; - p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[p_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_pancake_shadows, p_screen_size, p_viewport_size, p_default_bg_color, luminance_multiplier, p_opaque_render_buffers, p_apply_alpha_multiplier); + p_render_data->scene_data->update_ubo(scene_state.uniform_buffers[uniform_buffer_index], get_debug_draw_mode(), env, reflection_probe_instance, p_render_data->camera_attributes, p_pancake_shadows, p_screen_size, p_viewport_size, p_default_bg_color, luminance_multiplier, p_opaque_render_buffers, p_apply_alpha_multiplier); // now do implementation UBO @@ -769,15 +772,17 @@ void RenderForwardClustered::_setup_environment(const RenderDataRD *p_render_dat scene_state.ubo.ss_effects_flags = 0; } - if (p_index >= (int)scene_state.implementation_uniform_buffers.size()) { + if (uniform_buffer_index >= scene_state.implementation_uniform_buffers.size()) { uint32_t from = scene_state.implementation_uniform_buffers.size(); - scene_state.implementation_uniform_buffers.resize(p_index + 1); + scene_state.implementation_uniform_buffers.resize(uniform_buffer_index + 1); for (uint32_t i = from; i < scene_state.implementation_uniform_buffers.size(); i++) { scene_state.implementation_uniform_buffers[i] = RD::get_singleton()->uniform_buffer_create(sizeof(SceneState::UBO)); } } - RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[p_index], 0, sizeof(SceneState::UBO), &scene_state.ubo); + RD::get_singleton()->buffer_update(scene_state.implementation_uniform_buffers[uniform_buffer_index], 0, sizeof(SceneState::UBO), &scene_state.ubo); + + return uniform_buffer_index; } void RenderForwardClustered::SceneState::grow_instance_buffer(RenderListType p_render_list, uint32_t p_req_element_count, bool p_append) { @@ -1672,6 +1677,8 @@ void RenderForwardClustered::_process_sss(Ref p_render_buf } void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Color &p_default_bg_color) { + scene_state.used_uniform_buffer_count = 0; + RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); ERR_FAIL_NULL(p_render_data); @@ -1873,7 +1880,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); _setup_voxelgis(*p_render_data->voxel_gi_instances); - _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, false); + uint32_t depth_prepass_uniform_buffer_index = _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, false); // May have changed due to the above (light buffer enlarged, as an example). _update_render_base_uniform_set(); @@ -2102,7 +2109,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Render Depth Pre-Pass"); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, nullptr, RID(), samplers, depth_prepass_uniform_buffer_index); bool finish_depth = using_ssao || using_ssil || using_sdfgi || using_voxelgi || ce_pre_opaque_resolved_depth || ce_post_opaque_resolved_depth; RenderListParameters render_list_params(render_list[RENDER_LIST_OPAQUE].elements.ptr(), render_list[RENDER_LIST_OPAQUE].element_info.ptr(), render_list[RENDER_LIST_OPAQUE].elements.size(), reverse_cull, depth_pass_mode, 0, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); @@ -2159,9 +2166,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co // Shadow pass can change the base uniform set samplers. _update_render_base_uniform_set(); - _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, true, using_motion_pass); + uint32_t opaque_pass_uniform_buffer_index = _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, true, using_motion_pass); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, samplers, true); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_OPAQUE, p_render_data, radiance_texture, samplers, opaque_pass_uniform_buffer_index, true); { bool render_motion_pass = !render_list[RENDER_LIST_MOTION].elements.is_empty(); @@ -2208,7 +2215,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RENDER_TIMESTAMP("Render Motion Pass"); - rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, true); + rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_MOTION, p_render_data, radiance_texture, samplers, opaque_pass_uniform_buffer_index, true); RenderListParameters render_list_params(render_list[RENDER_LIST_MOTION].elements.ptr(), render_list[RENDER_LIST_MOTION].element_info.ptr(), render_list[RENDER_LIST_MOTION].elements.size(), reverse_cull, PASS_MODE_COLOR, color_pass_flags, rb_data.is_null(), p_render_data->directional_light_soft_shadows, rp_uniform_set, get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_WIREFRAME, Vector2(), p_render_data->scene_data->lod_distance_multiplier, p_render_data->scene_data->screen_mesh_lod_threshold, p_render_data->scene_data->view_count, 0, base_specialization); _render_list_with_draw_list(&render_list_params, color_framebuffer); @@ -2376,9 +2383,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co RD::get_singleton()->draw_command_begin_label("Render 3D Transparent Pass"); - rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, samplers, true); + uint32_t transparent_pass_uniform_buffer_index = _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, false); - _setup_environment(p_render_data, is_reflection_probe, screen_size, screen_size, p_default_bg_color, false); + rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_ALPHA, p_render_data, radiance_texture, samplers, transparent_pass_uniform_buffer_index, true); { uint32_t transparent_color_pass_flags = (color_pass_flags | uint32_t(COLOR_PASS_FLAG_TRANSPARENT)) & ~uint32_t(COLOR_PASS_FLAG_SEPARATE_SPECULAR); @@ -2754,8 +2761,6 @@ void RenderForwardClustered::_render_shadow_begin() { } void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const PagedArray &p_instances, const Projection &p_projection, const Transform3D &p_transform, float p_zfar, float p_bias, float p_normal_bias, bool p_reverse_cull_face, bool p_use_dp, bool p_use_dp_flip, bool p_use_pancake, float p_lod_distance_multiplier, float p_screen_mesh_lod_threshold, const Rect2i &p_rect, bool p_flip_y, bool p_clear_region, bool p_begin, bool p_end, RenderingMethod::RenderInfo *p_render_info, const Size2i &p_viewport_size, const Transform3D &p_main_cam_transform) { - uint32_t shadow_pass_index = scene_state.shadow_passes.size(); - SceneState::ShadowPass shadow_pass; RenderSceneDataRD scene_data; @@ -2785,7 +2790,7 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page if (viewport_size == Size2()) { viewport_size = screen_size; } - _setup_environment(&render_data, true, screen_size, viewport_size, Color(), false, false, p_use_pancake, shadow_pass_index); + uint32_t uniform_buffer_index = _setup_environment(&render_data, true, screen_size, viewport_size, Color(), false, false, p_use_pancake); if (get_debug_draw_mode() == RS::VIEWPORT_DEBUG_DRAW_DISABLE_LOD) { scene_data.screen_mesh_lod_threshold = 0.0; @@ -2825,6 +2830,8 @@ void RenderForwardClustered::_render_shadow_append(RID p_framebuffer, const Page shadow_pass.clear_depth = p_begin || p_clear_region; shadow_pass.rect = p_rect; + shadow_pass.uniform_buffer_index = uniform_buffer_index; + scene_state.shadow_passes.push_back(shadow_pass); } } @@ -2840,7 +2847,7 @@ void RenderForwardClustered::_render_shadow_process() { for (uint32_t i = 0; i < scene_state.shadow_passes.size(); i++) { //render passes need to be configured after instance buffer is done, since they need the latest version SceneState::ShadowPass &shadow_pass = scene_state.shadow_passes[i]; - shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), false, i); + shadow_pass.rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), shadow_pass.uniform_buffer_index, false); } RD::get_singleton()->draw_command_end_label(); @@ -2884,7 +2891,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con _update_render_base_uniform_set(); Size2i screen_size = RD::get_singleton()->framebuffer_get_size(p_fb); - _setup_environment(&render_data, true, screen_size, screen_size, Color(), false, false, false); + uint32_t uniform_buffer_index = _setup_environment(&render_data, true, screen_size, screen_size, Color(), false, false, false); PassMode pass_mode = PASS_MODE_SHADOW; @@ -2892,7 +2899,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), uniform_buffer_index); RENDER_TIMESTAMP("Render Collider Heightfield"); @@ -2936,14 +2943,14 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform if (viewport_size == Size2()) { viewport_size = screen_size; } - _setup_environment(&render_data, true, screen_size, viewport_size, Color()); + uint32_t uniform_buffer_index = _setup_environment(&render_data, true, screen_size, viewport_size, Color()); PassMode pass_mode = PASS_MODE_DEPTH_MATERIAL; _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); render_list[RENDER_LIST_SECONDARY].sort_by_key(); _fill_instance_data(RENDER_LIST_SECONDARY); - RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), uniform_buffer_index); RENDER_TIMESTAMP("Render 3D Material"); @@ -2992,14 +2999,14 @@ void RenderForwardClustered::_render_uv2(const PagedArraysamplers_rd_get_default()); + RID rp_uniform_set = _setup_render_pass_uniform_set(RENDER_LIST_SECONDARY, nullptr, RID(), RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), uniform_buffer_index); RENDER_TIMESTAMP("Render 3D Material"); @@ -3111,9 +3118,9 @@ void RenderForwardClustered::_render_sdfgi(Ref p_render_bu RendererRD::MaterialStorage::store_transform(to_bounds.affine_inverse() * scene_data.cam_transform, scene_state.ubo.sdf_to_bounds); scene_data.emissive_exposure_normalization = p_exposure_normalization; - _setup_environment(&render_data, true, fb_size, fb_size, Color()); + uint32_t uniform_buffer_index = _setup_environment(&render_data, true, fb_size, fb_size, Color()); - RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture, RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); + RID rp_uniform_set = _setup_sdfgi_render_pass_uniform_set(p_albedo_texture, p_emission_texture, p_emission_aniso_texture, p_geom_facing_texture, RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default(), uniform_buffer_index); HashMap::Iterator E = sdfgi_framebuffer_size_cache.find(fb_size); if (!E) { @@ -3266,7 +3273,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { } } -RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, bool p_use_directional_shadow_atlas, int p_index) { +RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, uint32_t p_uniform_buffer_index, bool p_use_directional_shadow_atlas) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); @@ -3293,14 +3300,14 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(scene_state.uniform_buffers[p_index]); + u.append_id(scene_state.uniform_buffers[p_uniform_buffer_index]); uniforms.push_back(u); } { RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(scene_state.implementation_uniform_buffers[p_index]); + u.append_id(scene_state.implementation_uniform_buffers[p_uniform_buffer_index]); uniforms.push_back(u); } { @@ -3653,7 +3660,7 @@ RID RenderForwardClustered::_setup_render_pass_uniform_set(RenderListType p_rend return UniformSetCacheRD::get_singleton()->get_cache_vec(scene_shader.default_shader_rd, RENDER_PASS_UNIFORM_SET, uniforms); } -RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture, const RendererRD::MaterialStorage::Samplers &p_samplers) { +RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, uint32_t p_uniform_buffer_index) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); thread_local LocalVector uniforms; uniforms.clear(); @@ -3662,14 +3669,14 @@ RID RenderForwardClustered::_setup_sdfgi_render_pass_uniform_set(RID p_albedo_te RD::Uniform u; u.binding = 0; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(scene_state.uniform_buffers[0]); + u.append_id(scene_state.uniform_buffers[p_uniform_buffer_index]); uniforms.push_back(u); } { RD::Uniform u; u.binding = 1; u.uniform_type = RD::UNIFORM_TYPE_UNIFORM_BUFFER; - u.append_id(scene_state.implementation_uniform_buffers[0]); + u.append_id(scene_state.implementation_uniform_buffers[p_uniform_buffer_index]); uniforms.push_back(u); } { diff --git a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h index 5332563fac5..10507db89c7 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -174,8 +174,8 @@ private: uint64_t lightmap_texture_array_version = 0xFFFFFFFF; void _update_render_base_uniform_set(); - RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture, const RendererRD::MaterialStorage::Samplers &p_samplers); - RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, bool p_use_directional_shadow_atlas = false, int p_index = 0); + RID _setup_sdfgi_render_pass_uniform_set(RID p_albedo_texture, RID p_emission_texture, RID p_emission_aniso_texture, RID p_geom_facing_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, uint32_t p_uniform_buffer_index); + RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, const RendererRD::MaterialStorage::Samplers &p_samplers, uint32_t p_uniform_buffer_index, bool p_use_directional_shadow_atlas = false); struct BestFitNormal { BestFitNormalShaderRD shader; @@ -391,6 +391,7 @@ private: LocalVector uniform_buffers; LocalVector implementation_uniform_buffers; + uint32_t used_uniform_buffer_count = 0; LightmapData lightmaps[MAX_LIGHTMAPS]; RID lightmap_ids[MAX_LIGHTMAPS]; @@ -429,6 +430,8 @@ private: Rect2i rect; bool clear_depth; bool flip_cull; + + uint32_t uniform_buffer_index; }; LocalVector shadow_passes; @@ -438,7 +441,7 @@ private: static RenderForwardClustered *singleton; - void _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Size2 &p_viewport_size, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_apply_alpha_multiplier = false, bool p_pancake_shadows = false, int p_index = 0); + uint32_t _setup_environment(const RenderDataRD *p_render_data, bool p_no_fog, const Size2i &p_screen_size, const Size2 &p_viewport_size, const Color &p_default_bg_color, bool p_opaque_render_buffers = false, bool p_apply_alpha_multiplier = false, bool p_pancake_shadows = false); void _setup_voxelgis(const PagedArray &p_voxelgis); void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray &p_lightmaps, const Transform3D &p_cam_transform);