1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-03 16:55:53 +00:00

Merge pull request #78598 from BastiaanOlij/resolve_depth_buffer_mobile

Resolve depth buffer in mobile renderer when required
This commit is contained in:
Thaddeus Crews
2025-11-20 11:10:48 -06:00
12 changed files with 152 additions and 37 deletions

View File

@@ -194,7 +194,7 @@ RID RendererSceneRenderImplementation::RenderForwardMobile::RenderBufferDataForw
return RID();
}
RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type) {
RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(FramebufferConfigType p_config_type, bool p_resolve_depth) {
ERR_FAIL_NULL_V(render_buffers, RID());
RendererRD::TextureStorage *texture_storage = RendererRD::TextureStorage::get_singleton();
@@ -225,17 +225,22 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
Vector<RID> textures;
int color_buffer_id = 0;
textures.push_back(use_msaa ? render_buffers->get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer
textures.push_back(use_msaa ? render_buffers->get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer
int depth_buffer_id = 1;
textures.push_back(use_msaa ? render_buffers->get_color_msaa() : render_buffers->get_internal_texture()); // 0 - color buffer.
textures.push_back(use_msaa ? render_buffers->get_depth_msaa() : render_buffers->get_depth_texture()); // 1 - depth buffer.
if (vrs_texture.is_valid()) {
textures.push_back(vrs_texture); // 2 - vrs texture
textures.push_back(vrs_texture); // 2 - vrs texture.
}
if (use_msaa) {
color_buffer_id = textures.size();
textures.push_back(render_buffers->get_internal_texture()); // color buffer for resolve
textures.push_back(render_buffers->get_internal_texture()); // Color buffer for resolve.
}
if (use_msaa && p_resolve_depth) {
depth_buffer_id = textures.size();
textures.push_back(render_buffers->get_depth_texture()); // Depth buffer for resolve.
}
// Now define our subpasses
// Now define our subpasses.
Vector<RD::FramebufferPass> passes;
switch (p_config_type) {
@@ -245,8 +250,13 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
pass.depth_attachment = 1;
if (use_msaa) {
// Add resolve
// Add color resolve.
pass.resolve_attachments.push_back(color_buffer_id);
if (p_resolve_depth) {
// Add depth resolve.
pass.depth_resolve_attachment = depth_buffer_id;
}
}
passes.push_back(pass);
@@ -257,7 +267,7 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
Size2i target_size = render_buffers->get_target_size();
Size2i internal_size = render_buffers->get_internal_size();
// can't do our blit pass if resolutions don't match, this should already have been checked.
// Can't do our blit pass if resolutions don't match, this should already have been checked.
ERR_FAIL_COND_V(target_size != internal_size, RID());
RD::FramebufferPass pass;
@@ -265,13 +275,18 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
pass.depth_attachment = 1;
if (use_msaa) {
// add resolve
// Add color resolve.
pass.resolve_attachments.push_back(color_buffer_id);
if (p_resolve_depth) {
// Add depth resolve.
pass.depth_resolve_attachment = depth_buffer_id;
}
}
passes.push_back(pass);
// - add blit to 2D pass
// Add blit to 2D pass.
RID render_target = render_buffers->get_render_target();
ERR_FAIL_COND_V(render_target.is_null(), RID());
RID target_buffer;
@@ -284,12 +299,12 @@ RID RenderForwardMobile::RenderBufferDataForwardMobile::get_color_fbs(Framebuffe
ERR_FAIL_COND_V(target_buffer.is_null(), RID());
int target_buffer_id = textures.size();
textures.push_back(target_buffer); // target buffer
textures.push_back(target_buffer); // Target buffer.
RD::FramebufferPass blit_pass;
blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer
blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer
// this doesn't need VRS
blit_pass.input_attachments.push_back(color_buffer_id); // Read from our (resolved) color buffer.
blit_pass.color_attachments.push_back(target_buffer_id); // Write into our target buffer.
// This doesn't need VRS or depth.
passes.push_back(blit_pass);
return FramebufferCacheRD::get_singleton()->get_cache_multipass(textures, passes, view_count);
@@ -807,9 +822,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RENDER_TIMESTAMP("Setup 3D Scene");
bool has_depth_texture_override = false;
bool supports_depth_resolve = RenderingDevice::get_singleton()->has_feature(RD::SUPPORTS_FRAMEBUFFER_DEPTH_RESOLVE);
RID render_target = rb->get_render_target();
if (render_target.is_valid()) {
p_render_data->scene_data->calculate_motion_vectors = RendererRD::TextureStorage::get_singleton()->render_target_get_override_velocity(render_target).is_valid();
p_render_data->scene_data->calculate_motion_vectors = texture_storage->render_target_get_override_velocity(render_target).is_valid();
has_depth_texture_override = texture_storage->render_target_get_override_depth(render_target).is_valid();
} else {
p_render_data->scene_data->calculate_motion_vectors = false;
}
@@ -834,6 +853,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RS::ViewportMSAA msaa = rb->get_msaa_3d();
bool use_msaa = msaa != RS::VIEWPORT_MSAA_DISABLED;
bool resolve_depth_buffer = (use_msaa && has_depth_texture_override); // We'll check more conditions later.
bool ce_has_post_opaque = _has_compositor_effect(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_POST_OPAQUE, p_render_data);
bool ce_has_pre_transparent = _has_compositor_effect(RS::COMPOSITOR_EFFECT_CALLBACK_TYPE_PRE_TRANSPARENT, p_render_data);
@@ -937,6 +957,7 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
if (use_msaa && p_render_data->environment.is_valid() && RSG::camera_attributes->camera_attributes_uses_dof(p_render_data->camera_attributes)) {
// Need to resolve depth texture for DOF when using MSAA.
scene_state.used_depth_texture = true;
resolve_depth_buffer = true;
}
if (scene_state.used_screen_texture || scene_state.used_depth_texture) {
@@ -945,13 +966,17 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
using_subpass_post_process = false;
}
if (use_msaa && (global_surface_data.depth_texture_used || scene_state.used_depth_texture)) {
resolve_depth_buffer = true;
}
if (using_subpass_post_process) {
// We can do all in one go.
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_AND_POST_PASS);
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_AND_POST_PASS, resolve_depth_buffer && supports_depth_resolve);
global_pipeline_data_required.use_subpass_post_pass = true;
} else {
// We separate things out.
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_PASS);
framebuffer = rb_data->get_color_fbs(RenderBufferDataForwardMobile::FB_CONFIG_RENDER_PASS, resolve_depth_buffer && supports_depth_resolve);
global_pipeline_data_required.use_separate_post_pass = true;
}
samplers = rb->get_samplers();
@@ -1242,8 +1267,6 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Render Transparent Subpass
}
// note if we are using MSAA we should get an automatic resolve through our subpass configuration.
// blit to tonemap
if (rb_data.is_valid() && using_subpass_post_process) {
_post_process_subpass(p_render_data->render_buffers->get_internal_texture(), framebuffer, p_render_data);
@@ -1252,6 +1275,13 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
RD::get_singleton()->draw_command_end_label(); // Render 3D Pass / Render Reflection Probe Pass
RD::get_singleton()->draw_list_end();
// note, if MSAA is used we should get an automatic resolve of the color buffer here.
if (use_msaa && has_depth_texture_override && !supports_depth_resolve) {
// We don't have a fallback for this, See PR #111322
WARN_PRINT_ONCE("MSAA Depth buffer resolve is not supported on this platform.");
}
} else {
// We're done with our subpasses so end our container pass
// note, if MSAA is used we should get an automatic resolve of the color buffer here.
@@ -1274,12 +1304,17 @@ void RenderForwardMobile::_render_scene(RenderDataRD *p_render_data, const Color
}
}
if (use_msaa && has_depth_texture_override && !supports_depth_resolve) {
// We don't have a fallback for this, See PR #111322
WARN_PRINT_ONCE("MSAA Depth buffer resolve is not supported on this platform.");
}
if (scene_state.used_depth_texture || global_surface_data.depth_texture_used) {
_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, use_msaa);
_render_buffers_copy_depth_texture(p_render_data, use_msaa && !supports_depth_resolve); // Note, once fallback for has_depth_texture_override works, we also don't need to do our resolve here.
}
}

View File

@@ -86,7 +86,7 @@ private:
FB_CONFIG_MAX
};
RID get_color_fbs(FramebufferConfigType p_config_type);
RID get_color_fbs(FramebufferConfigType p_config_type, bool p_resolve_depth = false);
virtual void free_data() override;
virtual void configure(RenderSceneBuffersRD *p_render_buffers) override;

View File

@@ -58,6 +58,7 @@ class FramebufferCacheRD : public Object {
static _FORCE_INLINE_ uint32_t _hash_pass(const RD::FramebufferPass &p, uint32_t h) {
h = hash_murmur3_one_32(p.depth_attachment, h);
h = hash_murmur3_one_32(p.depth_resolve_attachment, h);
h = hash_murmur3_one_32(p.color_attachments.size(), h);
for (int i = 0; i < p.color_attachments.size(); i++) {
@@ -82,6 +83,10 @@ class FramebufferCacheRD : public Object {
return false;
}
if (a.depth_resolve_attachment != b.depth_resolve_attachment) {
return false;
}
if (a.color_attachments.size() != b.color_attachments.size()) {
return false;
}

View File

@@ -730,7 +730,11 @@ uint32_t RenderSceneBuffersRD::get_color_usage_bits(bool p_resolve, bool p_msaa,
}
RD::DataFormat RenderSceneBuffersRD::get_depth_format(bool p_resolve, bool p_msaa, bool p_storage) {
if (p_resolve) {
// TODO Our rendering engine does not support just having a depth attachment, it always assumed we combine with stencil.
// We thus can't configure our depth resolve with RD::DATA_FORMAT_R32_SFLOAT.
// We should add support for TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT or add a TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT
if (p_resolve && !RenderingDevice::get_singleton()->has_feature(RD::SUPPORTS_FRAMEBUFFER_DEPTH_RESOLVE)) {
return RD::DATA_FORMAT_R32_SFLOAT;
} else {
const RenderingDeviceCommons::DataFormat preferred_formats[2] = {
@@ -749,7 +753,13 @@ uint32_t RenderSceneBuffersRD::get_depth_usage_bits(bool p_resolve, bool p_msaa,
if (p_msaa) {
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | RD::TEXTURE_USAGE_CAN_COPY_FROM_BIT;
} else if (p_resolve) {
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT | (p_storage ? RD::TEXTURE_USAGE_STORAGE_BIT : 0);
usage_bits |= RD::TEXTURE_USAGE_CAN_COPY_TO_BIT;
if (p_storage) {
usage_bits |= RD::TEXTURE_USAGE_STORAGE_BIT;
} else if (RenderingDevice::get_singleton()->has_feature(RD::SUPPORTS_FRAMEBUFFER_DEPTH_RESOLVE)) {
// We're able to resolve depth in (sub)passes and we make use of this in our mobile renderer.
usage_bits |= RD::TEXTURE_USAGE_DEPTH_RESOLVE_ATTACHMENT_BIT;
}
} else {
usage_bits |= RD::TEXTURE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
}