From 9b91750fb1cecea72fbd8ee155d3ad22754917c1 Mon Sep 17 00:00:00 2001 From: Dario Date: Tue, 5 Sep 2023 11:41:57 -0300 Subject: [PATCH] Fix mipmap bias behavior by refactoring how samplers are created by Material Storage. Introduces a new structure to store samplers created with certain parameters instead of storing a 'custom' set of samplers. Allows viewports to correctly configure the mipmap bias and use it when rendering the scene. --- .../rendering/renderer_rd/environment/fog.cpp | 2 +- .../rendering/renderer_rd/environment/sky.cpp | 2 +- .../render_forward_clustered.cpp | 48 +-- .../render_forward_clustered.h | 7 +- .../forward_mobile/render_forward_mobile.cpp | 42 +-- .../forward_mobile/render_forward_mobile.h | 2 +- .../renderer_rd/renderer_canvas_render_rd.cpp | 2 +- .../renderer_rd/renderer_scene_render_rd.h | 1 - .../storage_rd/material_storage.cpp | 336 +++++++----------- .../renderer_rd/storage_rd/material_storage.h | 34 +- .../storage_rd/particles_storage.cpp | 2 +- .../storage_rd/render_scene_buffers_rd.cpp | 50 +-- .../storage_rd/render_scene_buffers_rd.h | 12 + 13 files changed, 241 insertions(+), 299 deletions(-) diff --git a/servers/rendering/renderer_rd/environment/fog.cpp b/servers/rendering/renderer_rd/environment/fog.cpp index 8402cc74446..634f8c69df3 100644 --- a/servers/rendering/renderer_rd/environment/fog.cpp +++ b/servers/rendering/renderer_rd/environment/fog.cpp @@ -264,7 +264,7 @@ ALBEDO = vec3(1.0); uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); volumetric_fog.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, volumetric_fog.default_shader_rd, VolumetricFogShader::FogSet::FOG_SET_BASE); } diff --git a/servers/rendering/renderer_rd/environment/sky.cpp b/servers/rendering/renderer_rd/environment/sky.cpp index f94c701adaf..310aefe1b1a 100644 --- a/servers/rendering/renderer_rd/environment/sky.cpp +++ b/servers/rendering/renderer_rd/environment/sky.cpp @@ -874,7 +874,7 @@ void sky() { uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); sky_scene_state.uniform_set = RD::get_singleton()->uniform_set_create(uniforms, sky_shader.default_shader_rd, SKY_SET_UNIFORMS); } 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 2e64946fd26..5456e5b1829 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -1663,7 +1663,7 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co _setup_voxelgis(*p_render_data->voxel_gi_instances); _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); - _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) + _update_render_base_uniform_set(rb->get_samplers()); //may have changed due to the above (light buffer enlarged, as an example) _fill_render_list(RENDER_LIST_OPAQUE, p_render_data, PASS_MODE_COLOR, color_pass_flags, using_sdfgi, using_sdfgi || using_voxelgi); render_list[RENDER_LIST_OPAQUE].sort_by_key(); @@ -1889,6 +1889,9 @@ void RenderForwardClustered::_render_scene(RenderDataRD *p_render_data, const Co p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; p_render_data->scene_data->opaque_prepass_threshold = 0.0f; + // Shadow pass can change the base uniform set samplers. + _update_render_base_uniform_set(rb->get_samplers()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, true); RENDER_TIMESTAMP("Render Opaque Pass"); @@ -2324,7 +2327,7 @@ void RenderForwardClustered::_render_shadow_pass(RID p_light, RID p_shadow_atlas void RenderForwardClustered::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); render_list[RENDER_LIST_SECONDARY].clear(); scene_state.instance_data[RENDER_LIST_SECONDARY].clear(); @@ -2448,7 +2451,7 @@ void RenderForwardClustered::_render_particle_collider_heightfield(RID p_fb, con render_data.cluster_max_elements = 32; render_data.instances = &p_instances; - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); _setup_environment(&render_data, true, Vector2(1, 1), true, Color(), false, false); @@ -2494,7 +2497,7 @@ void RenderForwardClustered::_render_material(const Transform3D &p_cam_transform scene_shader.enable_advanced_shader_group(); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -2545,7 +2548,7 @@ void RenderForwardClustered::_render_uv2(const PagedArraysamplers_rd_get_default()); _setup_environment(&render_data, true, Vector2(1, 1), false, Color()); @@ -2614,7 +2617,7 @@ void RenderForwardClustered::_render_sdfgi(Ref p_render_bu render_data.cluster_max_elements = 32; render_data.instances = &p_instances; - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); PassMode pass_mode = PASS_MODE_SDF; _fill_render_list(RENDER_LIST_SECONDARY, &render_data, pass_mode); @@ -2694,13 +2697,10 @@ void RenderForwardClustered::base_uniforms_changed() { render_base_uniform_set = RID(); } -void RenderForwardClustered::_update_render_base_uniform_set() { +void RenderForwardClustered::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - - if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version()) || base_uniform_set_updated) { - base_uniform_set_updated = false; + if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { RD::get_singleton()->free(render_base_uniform_set); } @@ -2724,22 +2724,22 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RID sampler; switch (decals_get_filter()) { case RS::DECAL_FILTER_NEAREST: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } @@ -2754,22 +2754,22 @@ void RenderForwardClustered::_update_render_base_uniform_set() { RID sampler; switch (light_projectors_get_filter()) { case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_custom(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } @@ -2860,7 +2860,7 @@ void RenderForwardClustered::_update_render_base_uniform_set() { uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(p_samplers.get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET); } 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 a89c77c652e..39584bae631 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -155,8 +155,7 @@ class RenderForwardClustered : public RendererSceneRenderRD { uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - bool base_uniform_set_updated = false; - void _update_render_base_uniform_set(); + void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers); 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); RID _setup_render_pass_uniform_set(RenderListType p_render_list, const RenderDataRD *p_render_data, RID p_radiance_texture, bool p_use_directional_shadow_atlas = false, int p_index = 0); @@ -633,10 +632,6 @@ public: virtual void setup_added_decal(const Transform3D &p_transform, const Vector3 &p_half_size) override; virtual void base_uniforms_changed() override; - _FORCE_INLINE_ virtual void update_uniform_sets() override { - base_uniform_set_updated = true; - _update_render_base_uniform_set(); - } /* SDFGI UPDATE */ diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp index 3f01ffa3c96..d5f81da29f0 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -743,7 +743,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _setup_lightmaps(p_render_data, *p_render_data->lightmaps, p_render_data->scene_data->cam_transform); _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, false); - _update_render_base_uniform_set(); //may have changed due to the above (light buffer enlarged, as an example) + _update_render_base_uniform_set(rb->get_samplers()); //may have changed due to the above (light buffer enlarged, as an example) RD::get_singleton()->draw_command_end_label(); // Render Setup @@ -881,6 +881,9 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color p_render_data->scene_data->directional_light_count = p_render_data->directional_light_count; + // Shadow pass can change the base uniform set samplers. + _update_render_base_uniform_set(rb->get_samplers()); + _setup_environment(p_render_data, is_reflection_probe, screen_size, !is_reflection_probe, p_default_bg_color, p_render_data->render_buffers.is_valid()); if (using_subpass_transparent && using_subpass_post_process) { @@ -1241,7 +1244,7 @@ void RenderForwardMobile::_render_shadow_pass(RID p_light, RID p_shadow_atlas, i void RenderForwardMobile::_render_shadow_begin() { scene_state.shadow_passes.clear(); RD::get_singleton()->draw_command_begin_label("Shadow Setup"); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); render_list[RENDER_LIST_SECONDARY].clear(); } @@ -1348,7 +1351,7 @@ void RenderForwardMobile::_render_material(const Transform3D &p_cam_transform, c RD::get_singleton()->draw_command_begin_label("Render 3D Material"); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); RenderSceneDataRD scene_data; scene_data.cam_projection = p_cam_projection; @@ -1399,7 +1402,7 @@ void RenderForwardMobile::_render_uv2(const PagedArray RD::get_singleton()->draw_command_begin_label("Render UV2"); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); RenderSceneDataRD scene_data; scene_data.dual_paraboloid_side = 0; @@ -1473,7 +1476,7 @@ void RenderForwardMobile::_render_particle_collider_heightfield(RID p_fb, const RD::get_singleton()->draw_command_begin_label("Render Collider Heightfield"); - _update_render_base_uniform_set(); + _update_render_base_uniform_set(RendererRD::MaterialStorage::get_singleton()->samplers_rd_get_default()); RenderSceneDataRD scene_data; scene_data.cam_projection = p_cam_projection; @@ -1517,9 +1520,8 @@ void RenderForwardMobile::base_uniforms_changed() { render_base_uniform_set = RID(); } -void RenderForwardMobile::_update_render_base_uniform_set() { +void RenderForwardMobile::_update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers) { RendererRD::LightStorage *light_storage = RendererRD::LightStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); if (render_base_uniform_set.is_null() || !RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set) || (lightmap_texture_array_version != light_storage->lightmap_array_get_version())) { if (render_base_uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(render_base_uniform_set)) { @@ -1547,22 +1549,22 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RID sampler; switch (decals_get_filter()) { case RS::DECAL_FILTER_NEAREST: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::DECAL_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } @@ -1577,22 +1579,22 @@ void RenderForwardMobile::_update_render_base_uniform_set() { RID sampler; switch (light_projectors_get_filter()) { case RS::LIGHT_PROJECTOR_FILTER_NEAREST: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_NEAREST_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; case RS::LIGHT_PROJECTOR_FILTER_LINEAR_MIPMAPS_ANISOTROPIC: { - sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + sampler = p_samplers.get_sampler(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); } break; } @@ -1675,7 +1677,7 @@ void RenderForwardMobile::_update_render_base_uniform_set() { uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(p_samplers.get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); render_base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, scene_shader.default_shader_rd, SCENE_UNIFORM_SET); } diff --git a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h index f2913dd1859..65723e5aa53 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.h @@ -200,7 +200,7 @@ private: uint64_t lightmap_texture_array_version = 0xFFFFFFFF; - void _update_render_base_uniform_set(); + void _update_render_base_uniform_set(const RendererRD::MaterialStorage::Samplers &p_samplers); void _fill_render_list(RenderListType p_render_list, const RenderDataRD *p_render_data, PassMode p_pass_mode, bool p_append = false); void _fill_element_info(RenderListType p_render_list, uint32_t p_offset = 0, int32_t p_max_elements = -1); diff --git a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp index b1ad7e16ed6..60078ee0cae 100644 --- a/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_canvas_render_rd.cpp @@ -1045,7 +1045,7 @@ RID RendererCanvasRenderRD::_create_base_uniform_set(RID p_to_render_target, boo uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); RID uniform_set = RD::get_singleton()->uniform_set_create(uniforms, shader.default_version_rd_shader, BASE_UNIFORM_SET); if (p_backbuffer) { diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 4bce6a172ec..211d191039d 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -280,7 +280,6 @@ public: RID render_buffers_get_default_voxel_gi_buffer(); virtual void base_uniforms_changed() = 0; - virtual void update_uniform_sets(){}; virtual void render_scene(const Ref &p_render_buffers, const CameraData *p_camera_data, const CameraData *p_prev_camera_data, const PagedArray &p_instances, const PagedArray &p_lights, const PagedArray &p_reflection_probes, const PagedArray &p_voxel_gi_instances, const PagedArray &p_decals, const PagedArray &p_lightmaps, const PagedArray &p_fog_volumes, RID p_environment, RID p_camera_attributes, RID p_shadow_atlas, RID p_occluder_debug_tex, RID p_reflection_atlas, RID p_reflection_probe, int p_reflection_probe_pass, float p_screen_mesh_lod_threshold, const RenderShadowData *p_render_shadows, int p_render_shadow_count, const RenderSDFGIData *p_render_sdfgi_regions, int p_render_sdfgi_region_count, const RenderSDFGIUpdateData *p_sdfgi_update_data = nullptr, RenderingMethod::RenderInfo *r_render_info = nullptr) override; diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp index 5c4fa1a47c3..c40b74743b2 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.cpp @@ -1088,6 +1088,37 @@ void MaterialStorage::MaterialData::set_as_used() { } } +/////////////////////////////////////////////////////////////////////////// +// MaterialStorage::Samplers + +Vector MaterialStorage::Samplers::get_uniforms(int p_first_index) const { + Vector uniforms; + + // Binding ids are aligned with samplers_inc.glsl. + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 0, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 1, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 2, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 3, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 4, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 5, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC][RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 6, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 7, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 8, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 9, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 10, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, p_first_index + 11, rids[RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC][RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED])); + + return uniforms; +} + +bool MaterialStorage::Samplers::is_valid() const { + return rids[1][1].is_valid(); +} + +bool MaterialStorage::Samplers::is_null() const { + return rids[1][1].is_null(); +} + /////////////////////////////////////////////////////////////////////////// // MaterialStorage @@ -1101,92 +1132,7 @@ MaterialStorage::MaterialStorage() { singleton = this; //default samplers - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - RD::SamplerState sampler_state; - switch (i) { - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.max_lod = 0; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.max_lod = 0; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - - } break; - default: { - } - } - switch (j) { - case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - } break; - default: { - } - } - - default_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); - } - } - - //custom sampler - sampler_rd_configure_custom(0.0f); + default_samplers = samplers_rd_allocate(); // buffers { //create index array for copy shaders @@ -1233,20 +1179,7 @@ MaterialStorage::~MaterialStorage() { RD::get_singleton()->free(quad_index_buffer); //array gets freed as dependency //def samplers - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - RD::get_singleton()->free(default_rd_samplers[i][j]); - } - } - - //custom samplers - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 0; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - if (custom_rd_samplers[i][j].is_valid()) { - RD::get_singleton()->free(custom_rd_samplers[i][j]); - } - } - } + samplers_rd_free(default_samplers); singleton = nullptr; } @@ -1263,102 +1196,6 @@ bool MaterialStorage::free(RID p_rid) { return false; } -/* Samplers */ - -void MaterialStorage::sampler_rd_configure_custom(float p_mipmap_bias) { - for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { - for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { - RD::SamplerState sampler_state; - switch (i) { - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.max_lod = 0; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.max_lod = 0; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.lod_bias = p_mipmap_bias; - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.lod_bias = p_mipmap_bias; - - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; - sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.lod_bias = p_mipmap_bias; - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - } break; - case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { - sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; - sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; - if (GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter")) { - sampler_state.mip_filter = RD::SAMPLER_FILTER_NEAREST; - } else { - sampler_state.mip_filter = RD::SAMPLER_FILTER_LINEAR; - } - sampler_state.lod_bias = p_mipmap_bias; - sampler_state.use_anisotropy = true; - sampler_state.anisotropy_max = 1 << int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - - } break; - default: { - } - } - switch (j) { - case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; - - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; - } break; - case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { - sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; - } break; - default: { - } - } - - if (custom_rd_samplers[i][j].is_valid()) { - RD::get_singleton()->free(custom_rd_samplers[i][j]); - } - - custom_rd_samplers[i][j] = RD::get_singleton()->sampler_create(sampler_state); - } - } -} - /* GLOBAL SHADER UNIFORM API */ int32_t MaterialStorage::_global_shader_uniform_allocate(uint32_t p_elements) { @@ -2400,24 +2237,99 @@ void MaterialStorage::material_update_dependency(RID p_material, DependencyTrack } } -Vector MaterialStorage::get_default_sampler_uniforms(int first_index) { - Vector uniforms; +MaterialStorage::Samplers MaterialStorage::samplers_rd_allocate(float p_mipmap_bias) const { + Samplers samplers; + samplers.mipmap_bias = p_mipmap_bias; + samplers.use_nearest_mipmap_filter = GLOBAL_GET("rendering/textures/default_filters/use_nearest_mipmap_filter"); + samplers.anisotropic_filtering_level = int(GLOBAL_GET("rendering/textures/default_filters/anisotropic_filtering_level")); - // Binding ids are aligned with samplers_inc.glsl. - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 0, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 1, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 2, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 3, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 4, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 5, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 6, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 7, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 8, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 9, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 10, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); - uniforms.push_back(RD::Uniform(RD::UNIFORM_TYPE_SAMPLER, first_index + 11, sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC, RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED))); + RD::SamplerFilter mip_filter = samplers.use_nearest_mipmap_filter ? RD::SAMPLER_FILTER_NEAREST : RD::SAMPLER_FILTER_LINEAR; + float anisotropy_max = float(1 << samplers.anisotropic_filtering_level); - return uniforms; + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + RD::SamplerState sampler_state; + switch (i) { + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.max_lod = 0; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.mip_filter = mip_filter; + sampler_state.lod_bias = samplers.mipmap_bias; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = mip_filter; + sampler_state.lod_bias = samplers.mipmap_bias; + + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.min_filter = RD::SAMPLER_FILTER_NEAREST; + sampler_state.mip_filter = mip_filter; + sampler_state.lod_bias = samplers.mipmap_bias; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = anisotropy_max; + } break; + case RS::CANVAS_ITEM_TEXTURE_FILTER_LINEAR_WITH_MIPMAPS_ANISOTROPIC: { + sampler_state.mag_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.min_filter = RD::SAMPLER_FILTER_LINEAR; + sampler_state.mip_filter = mip_filter; + sampler_state.lod_bias = samplers.mipmap_bias; + sampler_state.use_anisotropy = true; + sampler_state.anisotropy_max = anisotropy_max; + + } break; + default: { + } + } + switch (j) { + case RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_CLAMP_TO_EDGE; + + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_ENABLED: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_REPEAT; + } break; + case RS::CANVAS_ITEM_TEXTURE_REPEAT_MIRROR: { + sampler_state.repeat_u = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_v = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + sampler_state.repeat_w = RD::SAMPLER_REPEAT_MODE_MIRRORED_REPEAT; + } break; + default: { + } + } + + samplers.rids[i][j] = RD::get_singleton()->sampler_create(sampler_state); + } + } + + return samplers; +} + +void MaterialStorage::samplers_rd_free(Samplers &p_samplers) const { + for (int i = 1; i < RS::CANVAS_ITEM_TEXTURE_FILTER_MAX; i++) { + for (int j = 1; j < RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX; j++) { + if (p_samplers.rids[i][j].is_valid()) { + RD::get_singleton()->free(p_samplers.rids[i][j]); + p_samplers.rids[i][j] = RID(); + } + } + } } void MaterialStorage::material_set_data_request_function(ShaderType p_shader_type, MaterialStorage::MaterialDataRequestFunction p_function) { diff --git a/servers/rendering/renderer_rd/storage_rd/material_storage.h b/servers/rendering/renderer_rd/storage_rd/material_storage.h index ae97f43a3c4..403fd286b46 100644 --- a/servers/rendering/renderer_rd/storage_rd/material_storage.h +++ b/servers/rendering/renderer_rd/storage_rd/material_storage.h @@ -105,13 +105,27 @@ public: Vector texture_cache; }; + struct Samplers { + RID rids[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + float mipmap_bias = 0.0f; + bool use_nearest_mipmap_filter = false; + int anisotropic_filtering_level = 2; + + _FORCE_INLINE_ RID get_sampler(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) const { + return rids[p_filter][p_repeat]; + } + + Vector get_uniforms(int p_first_index) const; + bool is_valid() const; + bool is_null() const; + }; + private: static MaterialStorage *singleton; /* Samplers */ - RID default_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; - RID custom_rd_samplers[RS::CANVAS_ITEM_TEXTURE_FILTER_MAX][RS::CANVAS_ITEM_TEXTURE_REPEAT_MAX]; + Samplers default_samplers; /* Buffers */ @@ -335,18 +349,16 @@ public: /* Samplers */ + Samplers samplers_rd_allocate(float p_mipmap_bias = 0.0f) const; + void samplers_rd_free(Samplers &p_samplers) const; + _FORCE_INLINE_ RID sampler_rd_get_default(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { - return default_rd_samplers[p_filter][p_repeat]; - } - _FORCE_INLINE_ RID sampler_rd_get_custom(RS::CanvasItemTextureFilter p_filter, RS::CanvasItemTextureRepeat p_repeat) { - return custom_rd_samplers[p_filter][p_repeat]; + return default_samplers.get_sampler(p_filter, p_repeat); } - void sampler_rd_configure_custom(float mipmap_bias); - - Vector get_default_sampler_uniforms(int first_index); - - // void sampler_rd_set_default(float p_mipmap_bias); + _FORCE_INLINE_ const Samplers &samplers_rd_get_default() const { + return default_samplers; + } /* Buffers */ diff --git a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp index 3a415e97e0e..9f1b2d8c388 100644 --- a/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp +++ b/servers/rendering/renderer_rd/storage_rd/particles_storage.cpp @@ -152,7 +152,7 @@ void process() { uniforms.push_back(u); } - uniforms.append_array(material_storage->get_default_sampler_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); + uniforms.append_array(material_storage->samplers_rd_get_default().get_uniforms(SAMPLERS_BINDING_FIRST_INDEX)); particles_shader.base_uniform_set = RD::get_singleton()->uniform_set_create(uniforms, particles_shader.default_shader_rd, BASE_UNIFORM_SET); } diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp index 71bc21d5d48..c45189283a5 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.cpp @@ -29,8 +29,8 @@ /**************************************************************************/ #include "render_scene_buffers_rd.h" +#include "core/config/project_settings.h" #include "servers/rendering/renderer_rd/renderer_scene_render_rd.h" -#include "servers/rendering/renderer_rd/storage_rd/material_storage.h" #include "servers/rendering/renderer_rd/storage_rd/texture_storage.h" RenderSceneBuffersRD::RenderSceneBuffersRD() { @@ -40,6 +40,8 @@ RenderSceneBuffersRD::~RenderSceneBuffersRD() { cleanup(); data_buffers.clear(); + + RendererRD::MaterialStorage::get_singleton()->samplers_rd_free(samplers); } void RenderSceneBuffersRD::_bind_methods() { @@ -90,6 +92,27 @@ void RenderSceneBuffersRD::free_named_texture(NamedTexture &p_named_texture) { p_named_texture.slices.clear(); // slices should be freed automatically as dependents... } +void RenderSceneBuffersRD::update_samplers() { + float computed_mipmap_bias = texture_mipmap_bias; + + if (use_taa) { + // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. + // This restores sharpness in still images to be roughly at the same level as without TAA, + // but moving scenes will still be blurrier. + computed_mipmap_bias -= 0.5; + } + + if (screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { + // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. + // If both TAA and FXAA are enabled, combine their negative LOD biases together. + computed_mipmap_bias -= 0.25; + } + + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + material_storage->samplers_rd_free(samplers); + samplers = material_storage->samplers_rd_allocate(computed_mipmap_bias); +} + void RenderSceneBuffersRD::cleanup() { // Free our data buffers (but don't destroy them) for (KeyValue> &E : data_buffers) { @@ -105,7 +128,6 @@ void RenderSceneBuffersRD::cleanup() { void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_config) { RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton(); - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); render_target = p_config->get_render_target(); target_size = p_config->get_target_size(); @@ -123,23 +145,10 @@ void RenderSceneBuffersRD::configure(const RenderSceneBuffersConfiguration *p_co ERR_FAIL_COND_MSG(view_count == 0, "Must have at least 1 view"); - if (use_taa) { - // Use negative mipmap LOD bias when TAA is enabled to compensate for loss of sharpness. - // This restores sharpness in still images to be roughly at the same level as without TAA, - // but moving scenes will still be blurrier. - texture_mipmap_bias -= 0.5; - } + update_samplers(); - if (screen_space_aa == RS::VIEWPORT_SCREEN_SPACE_AA_FXAA) { - // Use negative mipmap LOD bias when FXAA is enabled to compensate for loss of sharpness. - // If both TAA and FXAA are enabled, combine their negative LOD biases together. - texture_mipmap_bias -= 0.25; - } - - material_storage->sampler_rd_configure_custom(texture_mipmap_bias); - - // need to check if we really need to do this here.. - RendererSceneRenderRD::get_singleton()->update_uniform_sets(); + // Notify the renderer the base uniform needs to be recreated. + RendererSceneRenderRD::get_singleton()->base_uniforms_changed(); // cleanout any old buffers we had. cleanup(); @@ -243,8 +252,9 @@ void RenderSceneBuffersRD::set_fsr_sharpness(float p_fsr_sharpness) { } void RenderSceneBuffersRD::set_texture_mipmap_bias(float p_texture_mipmap_bias) { - RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); - material_storage->sampler_rd_configure_custom(p_texture_mipmap_bias); + texture_mipmap_bias = p_texture_mipmap_bias; + + update_samplers(); } void RenderSceneBuffersRD::set_use_debanding(bool p_use_debanding) { diff --git a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h index 85140c674c0..ddd64cb41c3 100644 --- a/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h +++ b/servers/rendering/renderer_rd/storage_rd/render_scene_buffers_rd.h @@ -34,6 +34,7 @@ #include "../effects/vrs.h" #include "../framebuffer_cache_rd.h" #include "core/templates/hash_map.h" +#include "material_storage.h" #include "render_buffer_custom_data_rd.h" #include "servers/rendering/rendering_device.h" #include "servers/rendering/rendering_device_binds.h" @@ -153,6 +154,11 @@ private: // Data buffers mutable HashMap> data_buffers; + // Samplers. + RendererRD::MaterialStorage::Samplers samplers; + + void update_samplers(); + protected: static void _bind_methods(); @@ -252,6 +258,12 @@ public: RID get_velocity_buffer(bool p_get_msaa); RID get_velocity_buffer(bool p_get_msaa, uint32_t p_layer); + // Samplers adjusted with the mipmap bias that is best fit for the configuration of these render buffers. + + _FORCE_INLINE_ RendererRD::MaterialStorage::Samplers get_samplers() const { + return samplers; + } + //////////////////////////////////////////////////////////////////////////////////////////////////////////// // Our classDB doesn't support calling our normal exposed functions