Give every pass its own unique environment uniform buffer.

This commit is contained in:
Skyth
2026-01-20 18:17:24 +03:00
parent 78c6632eb1
commit 1d9910cac4
2 changed files with 45 additions and 35 deletions

View File

@@ -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<RenderSceneBuffersRD> 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<RenderSceneBuffersRD> 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<RenderGeometryInstance *> &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 PagedArray<RenderGeometryInstance
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");
@@ -3111,9 +3118,9 @@ void RenderForwardClustered::_render_sdfgi(Ref<RenderSceneBuffersRD> 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<Size2i, RID>::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<RD::Uniform> 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);
}
{

View File

@@ -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<RID> uniform_buffers;
LocalVector<RID> 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<ShadowPass> 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<RID> &p_voxelgis);
void _setup_lightmaps(const RenderDataRD *p_render_data, const PagedArray<RID> &p_lightmaps, const Transform3D &p_cam_transform);