From a8efa55bedbb13d966526ccfdd102caa564bade1 Mon Sep 17 00:00:00 2001 From: clayjohn Date: Tue, 15 Jul 2025 05:37:09 -0700 Subject: [PATCH] Add depth resolve to the mobile renderer --- .../rendering/renderer_rd/effects/resolve.cpp | 63 ++++++++++++++++--- .../rendering/renderer_rd/effects/resolve.h | 14 ++++- .../render_forward_clustered.cpp | 6 -- .../render_forward_clustered.h | 2 - .../forward_mobile/render_forward_mobile.cpp | 8 +-- .../renderer_rd/renderer_scene_render_rd.cpp | 15 ++++- .../renderer_rd/renderer_scene_render_rd.h | 4 +- .../shaders/effects/resolve_raster.glsl | 46 ++++++++++++++ 8 files changed, 131 insertions(+), 27 deletions(-) create mode 100644 servers/rendering/renderer_rd/shaders/effects/resolve_raster.glsl diff --git a/servers/rendering/renderer_rd/effects/resolve.cpp b/servers/rendering/renderer_rd/effects/resolve.cpp index 576903945ba..ffbdaac1b76 100644 --- a/servers/rendering/renderer_rd/effects/resolve.cpp +++ b/servers/rendering/renderer_rd/effects/resolve.cpp @@ -34,26 +34,43 @@ using namespace RendererRD; -Resolve::Resolve() { - Vector resolve_modes; - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); - resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); +Resolve::Resolve(bool p_prefer_raster_effects) { + prefer_raster_effects = p_prefer_raster_effects; - resolve.shader.initialize(resolve_modes); + if (prefer_raster_effects) { + Vector resolve_modes; + resolve_modes.push_back(""); - resolve.shader_version = resolve.shader.version_create(); + resolve_raster.shader.initialize(resolve_modes); + resolve_raster.shader_version = resolve_raster.shader.version_create(); + resolve_raster.pipeline.setup(resolve_raster.shader.version_get_shader(resolve_raster.shader_version, 0), RD::RENDER_PRIMITIVE_TRIANGLES, RD::PipelineRasterizationState(), RD::PipelineMultisampleState(), RD::PipelineDepthStencilState(), RD::PipelineColorBlendState::create_disabled(), 0); + } else { + Vector resolve_modes; + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_GI\n#define VOXEL_GI_RESOLVE\n"); + resolve_modes.push_back("\n#define MODE_RESOLVE_DEPTH\n"); - for (int i = 0; i < RESOLVE_MODE_MAX; i++) { - resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + resolve.shader.initialize(resolve_modes); + + resolve.shader_version = resolve.shader.version_create(); + + for (int i = 0; i < RESOLVE_MODE_MAX; i++) { + resolve.pipelines[i] = RD::get_singleton()->compute_pipeline_create(resolve.shader.version_get_shader(resolve.shader_version, i)); + } } } Resolve::~Resolve() { - resolve.shader.version_free(resolve.shader_version); + if (prefer_raster_effects) { + resolve_raster.shader.version_free(resolve_raster.shader_version); + } else { + resolve.shader.version_free(resolve.shader_version); + } } void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute shader resolve with the mobile renderer."); + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -96,6 +113,8 @@ void Resolve::resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID } void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples) { + ERR_FAIL_COND_MSG(prefer_raster_effects, "Can't use the compute shader resolve with the mobile renderer."); + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); ERR_FAIL_NULL(uniform_set_cache); MaterialStorage *material_storage = MaterialStorage::get_singleton(); @@ -127,3 +146,27 @@ void Resolve::resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_scr RD::get_singleton()->compute_list_end(); } + +void Resolve::resolve_depth_raster(RID p_source_rd_texture, RID p_dest_framebuffer, int p_samples) { + RendererRD::MaterialStorage *material_storage = RendererRD::MaterialStorage::get_singleton(); + UniformSetCacheRD *uniform_set_cache = UniformSetCacheRD::get_singleton(); + + memset(&resolve_raster.push_constant, 0, sizeof(ResolvePushConstant)); + resolve_raster.push_constant.samples = p_samples; + + RID default_sampler = material_storage->sampler_rd_get_default(RS::CANVAS_ITEM_TEXTURE_FILTER_NEAREST, RS::CANVAS_ITEM_TEXTURE_REPEAT_DISABLED); + + RD::Uniform u_source_rd_texture(RD::UNIFORM_TYPE_SAMPLER_WITH_TEXTURE, 0, Vector({ default_sampler, p_source_rd_texture })); + + RID shader = resolve_raster.shader.version_get_shader(resolve_raster.shader_version, 0); + ERR_FAIL_COND(shader.is_null()); + + RD::DrawListID draw_list = RD::get_singleton()->draw_list_begin(p_dest_framebuffer); + RD::get_singleton()->draw_list_bind_render_pipeline(draw_list, resolve_raster.pipeline.get_render_pipeline(RD::INVALID_ID, RD::get_singleton()->framebuffer_get_format(p_dest_framebuffer))); + RD::get_singleton()->draw_list_bind_uniform_set(draw_list, uniform_set_cache->get_cache(shader, 0, u_source_rd_texture), 0); + + RD::get_singleton()->draw_list_set_push_constant(draw_list, &resolve_raster.push_constant, sizeof(ResolvePushConstant)); + + RD::get_singleton()->draw_list_draw(draw_list, false, 1u, 3u); + RD::get_singleton()->draw_list_end(); +} diff --git a/servers/rendering/renderer_rd/effects/resolve.h b/servers/rendering/renderer_rd/effects/resolve.h index dea47fa8a7d..b34da500ecd 100644 --- a/servers/rendering/renderer_rd/effects/resolve.h +++ b/servers/rendering/renderer_rd/effects/resolve.h @@ -30,12 +30,16 @@ #pragma once +#include "servers/rendering/renderer_rd/pipeline_cache_rd.h" #include "servers/rendering/renderer_rd/shaders/effects/resolve.glsl.gen.h" +#include "servers/rendering/renderer_rd/shaders/effects/resolve_raster.glsl.gen.h" namespace RendererRD { class Resolve { private: + bool prefer_raster_effects; + struct ResolvePushConstant { int32_t screen_size[2]; int32_t samples; @@ -56,12 +60,20 @@ private: RID pipelines[RESOLVE_MODE_MAX]; //3 quality levels } resolve; + struct ResolveRasterShader { + ResolvePushConstant push_constant; + ResolveRasterShaderRD shader; + RID shader_version; + PipelineCacheRD pipeline; + } resolve_raster; + public: - Resolve(); + Resolve(bool p_prefer_raster_effects); ~Resolve(); void resolve_gi(RID p_source_depth, RID p_source_normal_roughness, RID p_source_voxel_gi, RID p_dest_depth, RID p_dest_normal_roughness, RID p_dest_voxel_gi, Vector2i p_screen_size, int p_samples); void resolve_depth(RID p_source_depth, RID p_dest_depth, Vector2i p_screen_size, int p_samples); + void resolve_depth_raster(RID p_source_rd_texture, RID p_dest_framebuffer, int p_samples); }; } // namespace RendererRD 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 456661d7126..7b3db4169ec 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.cpp @@ -5037,7 +5037,6 @@ RenderForwardClustered::RenderForwardClustered() { _update_shader_quality_settings(); _update_global_pipeline_data_requirements_from_project(); - resolve_effects = memnew(RendererRD::Resolve()); taa = memnew(RendererRD::TAA); fsr2_effect = memnew(RendererRD::FSR2Effect); ss_effects = memnew(RendererRD::SSEffects); @@ -5075,11 +5074,6 @@ RenderForwardClustered::~RenderForwardClustered() { } #endif - if (resolve_effects != nullptr) { - memdelete(resolve_effects); - resolve_effects = nullptr; - } - RD::get_singleton()->free(shadow_sampler); RSG::light_storage->directional_shadow_atlas_set_size(0); 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 b5c92ec1fe2..1c0a803c1a5 100644 --- a/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h +++ b/servers/rendering/renderer_rd/forward_clustered/render_forward_clustered.h @@ -37,7 +37,6 @@ #include "servers/rendering/renderer_rd/effects/metal_fx.h" #endif #include "servers/rendering/renderer_rd/effects/motion_vectors_store.h" -#include "servers/rendering/renderer_rd/effects/resolve.h" #include "servers/rendering/renderer_rd/effects/ss_effects.h" #include "servers/rendering/renderer_rd/effects/taa.h" #include "servers/rendering/renderer_rd/forward_clustered/scene_shader_forward_clustered.h" @@ -716,7 +715,6 @@ private: /* Effects */ - RendererRD::Resolve *resolve_effects = nullptr; RendererRD::TAA *taa = nullptr; RendererRD::FSR2Effect *fsr2_effect = nullptr; RendererRD::SSEffects *ss_effects = nullptr; 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 e00e0294186..8361535c855 100644 --- a/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp +++ b/servers/rendering/renderer_rd/forward_mobile/render_forward_mobile.cpp @@ -233,8 +233,6 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe if (use_msaa) { color_buffer_id = textures.size(); textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve - - // TODO add support for resolving depth buffer!!! } // Now define our subpasses @@ -1248,7 +1246,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color RD::get_singleton()->draw_list_end(); } else { // We're done with our subpasses so end our container pass - // note, if MSAA is used we should get an automatic resolve here + // note, if MSAA is used we should get an automatic resolve of the color buffer here. RD::get_singleton()->draw_list_end(); @@ -1272,8 +1270,8 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color _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); + // Copy depth texture to backbuffer so we can read from it. + _render_buffers_copy_depth_texture(p_render_data, use_msaa); } } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp index 6cbc59b5981..cf4b37068a5 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.cpp @@ -412,7 +412,7 @@ void RendererSceneRenderRD::_render_buffers_ensure_depth_texture(const RenderDat 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) { +void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataRD *p_render_data, bool p_use_msaa) { Ref rb = p_render_data->render_buffers; ERR_FAIL_COND(rb.is_null()); @@ -433,7 +433,13 @@ void RendererSceneRenderRD::_render_buffers_copy_depth_texture(const RenderDataR copy_effects->copy_to_rect(depth_texture, depth_back_texture, Rect2i(0, 0, size.x, size.y)); } else { RID depth_back_fb = FramebufferCacheRD::get_singleton()->get_cache(depth_back_texture); - copy_effects->copy_to_fb_rect(depth_texture, depth_back_fb, Rect2i(0, 0, size.x, size.y)); + if (p_use_msaa) { + static const int texture_multisamples[RS::VIEWPORT_MSAA_MAX] = { 1, 2, 4, 8 }; + + resolve_effects->resolve_depth_raster(rb->get_depth_msaa(v), depth_back_fb, texture_multisamples[rb->get_msaa_3d()]); + } else { + copy_effects->copy_to_fb_rect(depth_texture, depth_back_fb, Rect2i(0, 0, size.x, size.y)); + } } } @@ -1612,6 +1618,7 @@ void RendererSceneRenderRD::init() { #ifdef METAL_ENABLED mfx_spatial = memnew(RendererRD::MFXSpatialEffect); #endif + resolve_effects = memnew(RendererRD::Resolve(!can_use_storage)); } RendererSceneRenderRD::~RendererSceneRenderRD() { @@ -1649,6 +1656,10 @@ RendererSceneRenderRD::~RendererSceneRenderRD() { } #endif + if (resolve_effects) { + memdelete(resolve_effects); + } + if (sky.sky_scene_state.uniform_set.is_valid() && RD::get_singleton()->uniform_set_is_valid(sky.sky_scene_state.uniform_set)) { RD::get_singleton()->free(sky.sky_scene_state.uniform_set); } diff --git a/servers/rendering/renderer_rd/renderer_scene_render_rd.h b/servers/rendering/renderer_rd/renderer_scene_render_rd.h index 9d5a127cba4..50947865a1e 100644 --- a/servers/rendering/renderer_rd/renderer_scene_render_rd.h +++ b/servers/rendering/renderer_rd/renderer_scene_render_rd.h @@ -39,6 +39,7 @@ #ifdef METAL_ENABLED #include "servers/rendering/renderer_rd/effects/metal_fx.h" #endif +#include "servers/rendering/renderer_rd/effects/resolve.h" #include "servers/rendering/renderer_rd/effects/smaa.h" #include "servers/rendering/renderer_rd/effects/tone_mapper.h" #include "servers/rendering/renderer_rd/effects/vrs.h" @@ -66,6 +67,7 @@ protected: RendererRD::ToneMapper *tone_mapper = nullptr; RendererRD::FSR *fsr = nullptr; RendererRD::VRS *vrs = nullptr; + RendererRD::Resolve *resolve_effects = nullptr; #ifdef METAL_ENABLED RendererRD::MFXSpatialEffect *mfx_spatial = nullptr; #endif @@ -108,7 +110,7 @@ protected: 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_copy_depth_texture(const RenderDataRD *p_render_data, bool p_use_msaa = false); 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); void _disable_clear_request(const RenderDataRD *p_render_data); diff --git a/servers/rendering/renderer_rd/shaders/effects/resolve_raster.glsl b/servers/rendering/renderer_rd/shaders/effects/resolve_raster.glsl new file mode 100644 index 00000000000..e3d77f56234 --- /dev/null +++ b/servers/rendering/renderer_rd/shaders/effects/resolve_raster.glsl @@ -0,0 +1,46 @@ +/* clang-format off */ +#[vertex] + +#version 450 + +#VERSION_DEFINES + +layout(location = 0) out vec2 uv_interp; +/* clang-format on */ + +void main() { + vec2 base_arr[3] = vec2[](vec2(-1.0, -1.0), vec2(-1.0, 3.0), vec2(3.0, -1.0)); + gl_Position = vec4(base_arr[gl_VertexIndex], 0.0, 1.0); + uv_interp = clamp(gl_Position.xy, vec2(0.0, 0.0), vec2(1.0, 1.0)) * 2.0; // saturate(x) * 2.0 +} + +/* clang-format off */ +#[fragment] + +#version 450 + +#VERSION_DEFINES + +layout(location = 0) in vec2 uv_interp; + +layout(set = 0, binding = 0) uniform sampler2DMS source_depth; + +layout(push_constant, std430) uniform Params { + ivec2 pad; + int sample_count; + int pad2; +} +params; + +layout (location = 0) out float out_depth; + +void main() { + ivec2 pos = ivec2(gl_FragCoord.xy); + + float depth_avg = 0.0; + for (int i = 0; i < params.sample_count; i++) { + depth_avg += texelFetch(source_depth, pos, i).r; + } + depth_avg /= float(params.sample_count); + out_depth = depth_avg; +}