Get rid of depth buffer workaround in the render pipeline code (#15407)

I originally wanted to get of the legacy IVideoDriver::setRenderTarget altogether,
but that ended up being too much work.
The remaining usage is in "dynamicshadowsrender.cpp".

Here's a comment I wrote about the workaround:

----------------------------------------

Use legacy call when there's single texture without depth texture
This means Irrlicht creates a depth texture for us and binds it to the FBO

This is currently necessary for a working depth buffer in the following cases:

- post-processing disabled, undersampling enabled
  (addUpscaling specifies no depth texture)

- post-processing disabled, 3d_mode = sidebyside / topbottom / crossview
  (populateSideBySidePipeline specifies no depth texture)

- post-processing disabled, 3d_mode = interlaced
  (probably, can't test since it's broken)
  (populateInterlacedPipeline specifies no depth texture)

With post-processing disabled, the world is rendered to the TextureBufferOutput
created in the functions listed above, so a depth buffer is needed
(-> this workaround is needed).
With post-processing enabled, only a fullscreen rectangle is rendered to
this TextureBufferOutput, so a depth buffer isn't actually needed.
But: These pipeline steps shouldn't rely on what ends up being rendered to
the TextureBufferOutput they provide, since that may change.

This workaround was added in 1e9640395468beb53f70303ef6b7aa72e395b7b4 /
https://irc.minetest.net/minetest-dev/2022-10-04#i_6021940

This workaround should be replaced by explicitly configuring depth
textures where needed.

----------------------------------------
This commit is contained in:
grorp 2024-11-15 11:38:56 +01:00 committed by GitHub
parent d4378a74d3
commit a9fe83126a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 54 additions and 27 deletions

@ -263,6 +263,8 @@ viewing_range (Viewing range) int 190 20 4000
# to the game world only, keeping the GUI intact. # to the game world only, keeping the GUI intact.
# It should give a significant performance boost at the cost of less detailed image. # It should give a significant performance boost at the cost of less detailed image.
# Higher values result in a less detailed image. # Higher values result in a less detailed image.
# Note: Undersampling is currently not supported if the "3d_mode" setting is set
# to a non-default value.
undersampling (Undersampling) int 1 1 8 undersampling (Undersampling) int 1 1 8
[**3D] [**3D]

@ -35,6 +35,13 @@ void InitInterlacedMaskStep::run(PipelineContext &context)
void populateInterlacedPipeline(RenderPipeline *pipeline, Client *client) void populateInterlacedPipeline(RenderPipeline *pipeline, Client *client)
{ {
// FIXME: "3d_mode = interlaced" is currently broken. Two options:
// 1. Remove it
// 2. Fix it
// If you fix it, make sure to test it with "enable_post_processing = false".
// You'll probably have to add a depth texture to make that combination work.
// Also, this code should probably use selectColorFormat/selectDepthFormat.
static const u8 TEXTURE_LEFT = 0; static const u8 TEXTURE_LEFT = 0;
static const u8 TEXTURE_RIGHT = 1; static const u8 TEXTURE_RIGHT = 1;
static const u8 TEXTURE_MASK = 2; static const u8 TEXTURE_MASK = 2;

@ -177,13 +177,6 @@ void TextureBufferOutput::activate(PipelineContext &context)
size = texture->getSize(); size = texture->getSize();
} }
// Use legacy call when there's single texture without depth texture
// This binds default depth buffer to the FBO
if (textures.size() == 1 && depth_stencil == NO_DEPTH_TEXTURE) {
driver->setRenderTarget(textures[0], m_clear, m_clear, context.clear_color);
return;
}
video::ITexture *depth_texture = nullptr; video::ITexture *depth_texture = nullptr;
if (depth_stencil != NO_DEPTH_TEXTURE) if (depth_stencil != NO_DEPTH_TEXTURE)
depth_texture = buffer->getTexture(depth_stencil); depth_texture = buffer->getTexture(depth_stencil);
@ -211,7 +204,7 @@ video::ITexture *DynamicSource::getTexture(u8 index)
void ScreenTarget::activate(PipelineContext &context) void ScreenTarget::activate(PipelineContext &context)
{ {
auto driver = context.device->getVideoDriver(); auto driver = context.device->getVideoDriver();
driver->setRenderTarget(nullptr, m_clear, m_clear, context.clear_color); driver->setRenderTargetEx(nullptr, m_clear ? video::ECBF_ALL : video::ECBF_NONE, context.clear_color);
driver->OnResize(size); driver->OnResize(size);
RenderTarget::activate(context); RenderTarget::activate(context);
} }

@ -104,9 +104,10 @@ static v2f getDownscaleFactor()
return v2f(1.0f / undersampling); return v2f(1.0f / undersampling);
} }
RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f downscale_factor) RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f downscale_factor, Client *client)
{ {
const int TEXTURE_UPSCALE = 0; const int TEXTURE_LOWRES_COLOR = 0;
const int TEXTURE_LOWRES_DEPTH = 1;
if (downscale_factor.X == 1.0f && downscale_factor.Y == 1.0f) if (downscale_factor.X == 1.0f && downscale_factor.Y == 1.0f)
return previousStep; return previousStep;
@ -115,13 +116,18 @@ RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f
if (g_settings->getBool("enable_post_processing")) if (g_settings->getBool("enable_post_processing"))
return previousStep; return previousStep;
auto driver = client->getSceneManager()->getVideoDriver();
video::ECOLOR_FORMAT color_format = selectColorFormat(driver);
video::ECOLOR_FORMAT depth_format = selectDepthFormat(driver);
// Initialize buffer // Initialize buffer
TextureBuffer *buffer = pipeline->createOwned<TextureBuffer>(); TextureBuffer *buffer = pipeline->createOwned<TextureBuffer>();
buffer->setTexture(TEXTURE_UPSCALE, downscale_factor, "upscale", video::ECF_A8R8G8B8); buffer->setTexture(TEXTURE_LOWRES_COLOR, downscale_factor, "lowres_color", color_format);
buffer->setTexture(TEXTURE_LOWRES_DEPTH, downscale_factor, "lowres_depth", depth_format);
// Attach previous step to the buffer // Attach previous step to the buffer
TextureBufferOutput *buffer_output = pipeline->createOwned<TextureBufferOutput>(buffer, TEXTURE_UPSCALE); TextureBufferOutput *buffer_output = pipeline->createOwned<TextureBufferOutput>(
buffer, std::vector<u8> {TEXTURE_LOWRES_COLOR}, TEXTURE_LOWRES_DEPTH);
previousStep->setRenderTarget(buffer_output); previousStep->setRenderTarget(buffer_output);
// Add upscaling step // Add upscaling step
@ -140,9 +146,25 @@ void populatePlainPipeline(RenderPipeline *pipeline, Client *client)
pipeline->addStep<DrawWield>(); pipeline->addStep<DrawWield>();
pipeline->addStep<MapPostFxStep>(); pipeline->addStep<MapPostFxStep>();
step3D = addUpscaling(pipeline, step3D, downscale_factor); step3D = addUpscaling(pipeline, step3D, downscale_factor, client);
step3D->setRenderTarget(pipeline->createOwned<ScreenTarget>()); step3D->setRenderTarget(pipeline->createOwned<ScreenTarget>());
pipeline->addStep<DrawHUD>(); pipeline->addStep<DrawHUD>();
} }
video::ECOLOR_FORMAT selectColorFormat(video::IVideoDriver *driver)
{
if (driver->queryTextureFormat(video::ECF_A16B16G16R16F))
return video::ECF_A16B16G16R16F;
return video::ECF_A8R8G8B8;
}
video::ECOLOR_FORMAT selectDepthFormat(video::IVideoDriver *driver)
{
if (driver->queryTextureFormat(video::ECF_D32))
return video::ECF_D32;
if (driver->queryTextureFormat(video::ECF_D24S8))
return video::ECF_D24S8;
return video::ECF_D16; // fallback depth format
}

@ -82,6 +82,9 @@ private:
}; };
std::unique_ptr<RenderStep> create3DStage(Client *client, v2f scale); std::unique_ptr<RenderStep> create3DStage(Client *client, v2f scale);
RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f downscale_factor); RenderStep* addUpscaling(RenderPipeline *pipeline, RenderStep *previousStep, v2f downscale_factor, Client *client);
void populatePlainPipeline(RenderPipeline *pipeline, Client *client); void populatePlainPipeline(RenderPipeline *pipeline, Client *client);
video::ECOLOR_FORMAT selectColorFormat(video::IVideoDriver *driver);
video::ECOLOR_FORMAT selectDepthFormat(video::IVideoDriver *driver);

@ -87,16 +87,8 @@ RenderStep *addPostProcessing(RenderPipeline *pipeline, RenderStep *previousStep
auto driver = client->getSceneManager()->getVideoDriver(); auto driver = client->getSceneManager()->getVideoDriver();
// configure texture formats // configure texture formats
video::ECOLOR_FORMAT color_format = video::ECF_A8R8G8B8; video::ECOLOR_FORMAT color_format = selectColorFormat(driver);
if (driver->queryTextureFormat(video::ECF_A16B16G16R16F)) video::ECOLOR_FORMAT depth_format = selectDepthFormat(driver);
color_format = video::ECF_A16B16G16R16F;
video::ECOLOR_FORMAT depth_format = video::ECF_D16; // fallback depth format
if (driver->queryTextureFormat(video::ECF_D32))
depth_format = video::ECF_D32;
else if (driver->queryTextureFormat(video::ECF_D24S8))
depth_format = video::ECF_D24S8;
// init post-processing buffer // init post-processing buffer
static const u8 TEXTURE_COLOR = 0; static const u8 TEXTURE_COLOR = 0;

@ -4,6 +4,7 @@
// Copyright (C) 2017 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru> // Copyright (C) 2017 numzero, Lobachevskiy Vitaliy <numzer0@yandex.ru>
#include "sidebyside.h" #include "sidebyside.h"
#include "client/client.h"
#include "client/hud.h" #include "client/hud.h"
#include "client/camera.h" #include "client/camera.h"
@ -35,6 +36,11 @@ void populateSideBySidePipeline(RenderPipeline *pipeline, Client *client, bool h
{ {
static const u8 TEXTURE_LEFT = 0; static const u8 TEXTURE_LEFT = 0;
static const u8 TEXTURE_RIGHT = 1; static const u8 TEXTURE_RIGHT = 1;
static const u8 TEXTURE_DEPTH = 2;
auto driver = client->getSceneManager()->getVideoDriver();
video::ECOLOR_FORMAT color_format = selectColorFormat(driver);
video::ECOLOR_FORMAT depth_format = selectDepthFormat(driver);
v2f offset; v2f offset;
if (horizontal) { if (horizontal) {
@ -47,15 +53,17 @@ void populateSideBySidePipeline(RenderPipeline *pipeline, Client *client, bool h
} }
TextureBuffer *buffer = pipeline->createOwned<TextureBuffer>(); TextureBuffer *buffer = pipeline->createOwned<TextureBuffer>();
buffer->setTexture(TEXTURE_LEFT, virtual_size_scale, "3d_render_left", video::ECF_A8R8G8B8); buffer->setTexture(TEXTURE_LEFT, virtual_size_scale, "3d_render_left", color_format);
buffer->setTexture(TEXTURE_RIGHT, virtual_size_scale, "3d_render_right", video::ECF_A8R8G8B8); buffer->setTexture(TEXTURE_RIGHT, virtual_size_scale, "3d_render_right", color_format);
buffer->setTexture(TEXTURE_DEPTH, virtual_size_scale, "3d_depthmap_sidebyside", depth_format);
auto step3D = pipeline->own(create3DStage(client, virtual_size_scale)); auto step3D = pipeline->own(create3DStage(client, virtual_size_scale));
// eyes // eyes
for (bool right : { false, true }) { for (bool right : { false, true }) {
pipeline->addStep<OffsetCameraStep>(flipped ? !right : right); pipeline->addStep<OffsetCameraStep>(flipped ? !right : right);
auto output = pipeline->createOwned<TextureBufferOutput>(buffer, right ? TEXTURE_RIGHT : TEXTURE_LEFT); auto output = pipeline->createOwned<TextureBufferOutput>(
buffer, std::vector<u8> {right ? TEXTURE_RIGHT : TEXTURE_LEFT}, TEXTURE_DEPTH);
pipeline->addStep<SetRenderTargetStep>(step3D, output); pipeline->addStep<SetRenderTargetStep>(step3D, output);
pipeline->addStep(step3D); pipeline->addStep(step3D);
pipeline->addStep<DrawWield>(); pipeline->addStep<DrawWield>();