Merge pull request #108636 from clayjohn/MSAA-depth-mobile

Add depth resolve to the mobile renderer
This commit is contained in:
Thaddeus Crews 2025-09-17 11:34:13 -05:00
commit 8c7c96e2c4
No known key found for this signature in database
GPG key ID: 8C6E5FEB5FC03CCC
8 changed files with 131 additions and 27 deletions

View file

@ -34,26 +34,43 @@
using namespace RendererRD;
Resolve::Resolve() {
Vector<String> 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<String> 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<String> 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<RID>({ 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();
}

View file

@ -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

View file

@ -5044,7 +5044,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);
@ -5082,11 +5081,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);

View file

@ -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;

View file

@ -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
@ -1252,7 +1250,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();
@ -1276,8 +1274,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);
}
}

View file

@ -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<RenderSceneBuffersRD> 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));
}
}
}
@ -1716,6 +1722,7 @@ void RendererSceneRenderRD::init() {
#ifdef METAL_ENABLED
mfx_spatial = memnew(RendererRD::MFXSpatialEffect);
#endif
resolve_effects = memnew(RendererRD::Resolve(!can_use_storage));
}
RendererSceneRenderRD::~RendererSceneRenderRD() {
@ -1753,6 +1760,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);
}

View file

@ -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);

View file

@ -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;
}