Moves post processing out of scene rendering to avoid framebuffer pass duplicate.

Comments By: phosit, Stan
Differential Revision: https://code.wildfiregames.com/D4827
This was SVN commit r27232.
This commit is contained in:
Vladislav Belov 2022-11-18 19:59:18 +00:00
parent 87843b5c4e
commit 8e51dfa91a
6 changed files with 155 additions and 74 deletions

View File

@ -233,9 +233,22 @@ void CGameView::BeginFrame()
m->Game->CachePlayerColors();
}
void CGameView::Render()
void CGameView::Prepare(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), *this);
g_Renderer.GetSceneRenderer().PrepareScene(deviceCommandContext, *this);
}
void CGameView::Render(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
g_Renderer.GetSceneRenderer().RenderScene(deviceCommandContext);
}
void CGameView::RenderOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
g_Renderer.GetSceneRenderer().RenderSceneOverlays(deviceCommandContext);
}
///////////////////////////////////////////////////////////

View File

@ -18,6 +18,7 @@
#ifndef INCLUDED_GAMEVIEW
#define INCLUDED_GAMEVIEW
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/Scene.h"
#include "simulation2/system/Entity.h"
@ -37,7 +38,7 @@ class CGameView : private Scene
NONCOPYABLE(CGameView);
public:
CGameView(CGame *pGame);
~CGameView();
~CGameView() override;
void SetViewport(const SViewPort& vp);
@ -53,7 +54,9 @@ public:
void Update(const float deltaRealTime);
void BeginFrame();
void Render();
void Prepare(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void Render(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
void RenderOverlays(Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
InReaction HandleEvent(const SDL_Event_* ev);

View File

@ -463,11 +463,52 @@ void CRenderer::RenderFrameImpl(const bool renderGUI, const bool renderLogger)
if (g_Game && g_Game->IsGameStarted())
{
g_Game->GetView()->Render();
}
g_Game->GetView()->Prepare(m->deviceCommandContext.get());
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
m->deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
CPostprocManager& postprocManager = g_Renderer.GetPostprocManager();
if (postprocManager.IsEnabled())
{
// We have to update the post process manager with real near/far planes
// that we use for the scene rendering.
postprocManager.SetDepthBufferClipPlanes(
m->sceneRenderer.GetViewCamera().GetNearPlane(),
m->sceneRenderer.GetViewCamera().GetFarPlane()
);
postprocManager.Initialize();
postprocManager.CaptureRenderOutput(m->deviceCommandContext.get());
}
else
{
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
}
g_Game->GetView()->Render(m->deviceCommandContext.get());
if (postprocManager.IsEnabled())
{
m->deviceCommandContext->EndFramebufferPass();
if (postprocManager.IsMultisampleEnabled())
postprocManager.ResolveMultisampleFramebuffer(m->deviceCommandContext.get());
postprocManager.ApplyPostproc(m->deviceCommandContext.get());
postprocManager.ReleaseRenderOutput(m->deviceCommandContext.get());
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
}
g_Game->GetView()->RenderOverlays(m->deviceCommandContext.get());
}
else
{
m->deviceCommandContext->BeginFramebufferPass(
m->deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
}
// If we're in Atlas game view, render special tools
if (g_AtlasGameLoop && g_AtlasGameLoop->view)

View File

@ -51,7 +51,6 @@
#include "renderer/ModelRenderer.h"
#include "renderer/OverlayRenderer.h"
#include "renderer/ParticleRenderer.h"
#include "renderer/PostprocManager.h"
#include "renderer/Renderer.h"
#include "renderer/RenderingOptions.h"
#include "renderer/RenderModifiers.h"
@ -757,13 +756,12 @@ void CSceneRenderer::RenderParticles(
}
}
// RenderSubmissions: force rendering of any batched objects
void CSceneRenderer::RenderSubmissions(
void CSceneRenderer::PrepareSubmissions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CBoundingBoxAligned& waterScissor)
{
PROFILE3("render submissions");
GPU_SCOPED_LABEL(deviceCommandContext, "Render submissions");
PROFILE3("prepare submissions");
GPU_SCOPED_LABEL(deviceCommandContext, "Prepare submissions");
m->skyManager.LoadAndUploadSkyTexturesIfNeeded(deviceCommandContext);
@ -774,8 +772,6 @@ void CSceneRenderer::RenderSubmissions(
CShaderDefines context = m->globalContext;
int cullGroup = CULL_DEFAULT;
// Set the camera
g_Renderer.SetViewport(m_ViewCamera.GetViewPort());
@ -829,29 +825,21 @@ void CSceneRenderer::RenderSubmissions(
RenderRefractions(deviceCommandContext, context, waterScissor);
if (g_RenderingOptions.GetWaterFancyEffects())
m->terrainRenderer.RenderWaterFoamOccluders(deviceCommandContext, cullGroup);
m->terrainRenderer.RenderWaterFoamOccluders(deviceCommandContext, CULL_DEFAULT);
}
}
}
deviceCommandContext->SetGraphicsPipelineState(
Renderer::Backend::MakeDefaultGraphicsPipelineStateDesc());
void CSceneRenderer::RenderSubmissions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CBoundingBoxAligned& waterScissor)
{
PROFILE3("render submissions");
GPU_SCOPED_LABEL(deviceCommandContext, "Render submissions");
CPostprocManager& postprocManager = g_Renderer.GetPostprocManager();
if (postprocManager.IsEnabled())
{
// We have to update the post process manager with real near/far planes
// that we use for the scene rendering.
postprocManager.SetDepthBufferClipPlanes(
m_ViewCamera.GetNearPlane(), m_ViewCamera.GetFarPlane()
);
postprocManager.Initialize();
postprocManager.CaptureRenderOutput(deviceCommandContext);
}
else
{
deviceCommandContext->BeginFramebufferPass(
deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
}
CShaderDefines context = m->globalContext;
constexpr int cullGroup = CULL_DEFAULT;
{
PROFILE3_GPU("clear buffers");
@ -912,24 +900,6 @@ void CSceneRenderer::RenderSubmissions(
RenderParticles(deviceCommandContext, cullGroup);
}
if (postprocManager.IsEnabled())
{
deviceCommandContext->EndFramebufferPass();
if (g_Renderer.GetPostprocManager().IsMultisampleEnabled())
g_Renderer.GetPostprocManager().ResolveMultisampleFramebuffer(deviceCommandContext);
postprocManager.ApplyPostproc(deviceCommandContext);
postprocManager.ReleaseRenderOutput(deviceCommandContext);
deviceCommandContext->BeginFramebufferPass(
deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
}
if (g_RenderingOptions.GetSilhouettes())
{
RenderSilhouettes(deviceCommandContext, context);
}
// render debug lines
if (g_RenderingOptions.GetDisplayFrustum())
DisplayFrustum();
@ -938,12 +908,6 @@ void CSceneRenderer::RenderSubmissions(
m->shadow.RenderDebugBounds();
m->silhouetteRenderer.RenderDebugBounds(deviceCommandContext);
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext);
// render overlays that should appear on top of all other objects
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
deviceCommandContext->EndFramebufferPass();
}
void CSceneRenderer::EndFrame()
@ -1093,8 +1057,7 @@ void CSceneRenderer::SubmitNonRecursive(CModel* model)
}
}
// Render the given scene
void CSceneRenderer::RenderScene(
void CSceneRenderer::PrepareScene(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Scene& scene)
{
m_CurrentScene = &scene;
@ -1131,19 +1094,18 @@ void CSceneRenderer::RenderScene(
}
}
CBoundingBoxAligned waterScissor;
if (m->waterManager.m_RenderWater)
{
waterScissor = m->terrainRenderer.ScissorWater(CULL_DEFAULT, m_ViewCamera);
m_WaterScissor = m->terrainRenderer.ScissorWater(CULL_DEFAULT, m_ViewCamera);
if (waterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater())
if (m_WaterScissor.GetVolume() > 0 && m->waterManager.WillRenderFancyWater())
{
if (g_RenderingOptions.GetWaterReflection())
{
m_CurrentCullGroup = CULL_REFLECTIONS;
CCamera reflectionCamera;
ComputeReflectionCamera(reflectionCamera, waterScissor);
ComputeReflectionCamera(reflectionCamera, m_WaterScissor);
scene.EnumerateObjects(reflectionCamera.GetFrustum(), this);
}
@ -1153,7 +1115,7 @@ void CSceneRenderer::RenderScene(
m_CurrentCullGroup = CULL_REFRACTIONS;
CCamera refractionCamera;
ComputeRefractionCamera(refractionCamera, waterScissor);
ComputeRefractionCamera(refractionCamera, m_WaterScissor);
scene.EnumerateObjects(refractionCamera.GetFrustum(), this);
}
@ -1162,12 +1124,35 @@ void CSceneRenderer::RenderScene(
m->waterManager.RenderWaves(deviceCommandContext, frustum);
}
}
else
m_WaterScissor = CBoundingBoxAligned{};
m_CurrentCullGroup = -1;
RenderSubmissions(deviceCommandContext, waterScissor);
PrepareSubmissions(deviceCommandContext, m_WaterScissor);
}
m_CurrentScene = NULL;
void CSceneRenderer::RenderScene(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
ENSURE(m_CurrentScene);
RenderSubmissions(deviceCommandContext, m_WaterScissor);
}
void CSceneRenderer::RenderSceneOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext)
{
if (g_RenderingOptions.GetSilhouettes())
{
RenderSilhouettes(deviceCommandContext, m->globalContext);
}
m->silhouetteRenderer.RenderDebugOverlays(deviceCommandContext);
// Render overlays that should appear on top of all other objects.
m->overlayRenderer.RenderForegroundOverlays(deviceCommandContext, m_ViewCamera);
m_CurrentScene = nullptr;
}
Scene& CSceneRenderer::GetScene()

View File

@ -21,6 +21,7 @@
#include "graphics/Camera.h"
#include "graphics/ShaderDefines.h"
#include "graphics/ShaderProgramPtr.h"
#include "maths/BoundingBoxAligned.h"
#include "ps/Singleton.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/RenderingOptions.h"
@ -94,10 +95,24 @@ public:
void SetSceneCamera(const CCamera& viewCamera, const CCamera& cullCamera);
/**
* Render the given scene immediately.
* @param scene a Scene object describing what should be rendered.
* Enumerate and submit all objects of the given scene which should be rendered.
* Must be called before RenderScene.
*/
void RenderScene(Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Scene& scene);
void PrepareScene(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext, Scene& scene);
/**
* Render submitted objects of the previously given scene.
*/
void RenderScene(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
/**
* Render overlays of the previously given scene.
* Must be called after RenderScene.
*/
void RenderSceneOverlays(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext);
/**
* Return the scene that is currently being rendered.
@ -193,6 +208,13 @@ protected:
void Submit(SOverlaySphere* overlay) override;
void SubmitNonRecursive(CModel* model) override;
/**
* Update and upload all needed data for submitted objects.
*/
void PrepareSubmissions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
const CBoundingBoxAligned& waterScissor);
// render any batched objects
void RenderSubmissions(
Renderer::Backend::IDeviceCommandContext* deviceCommandContext,
@ -272,6 +294,8 @@ protected:
Scene* m_CurrentScene;
int m_CurrentCullGroup;
CBoundingBoxAligned m_WaterScissor;
// current lighting setup
CLightEnv* m_LightEnv;

View File

@ -44,6 +44,8 @@
#include "ps/GameSetup/Config.h"
#include "ps/ProfileViewer.h"
#include "ps/VideoMode.h"
#include "renderer/backend/IDevice.h"
#include "renderer/backend/IDeviceCommandContext.h"
#include "renderer/Renderer.h"
#include "renderer/RenderingOptions.h"
#include "renderer/Scene.h"
@ -509,8 +511,10 @@ void ActorViewer::Render()
{
// TODO: ActorViewer should reuse CRenderer code and not duplicate it.
CSceneRenderer& sceneRenderer = g_Renderer.GetSceneRenderer();
// Set simulation context for rendering purposes
g_Renderer.GetSceneRenderer().SetSimulation(&m.Simulation2);
sceneRenderer.SetSimulation(&m.Simulation2);
// Find the centre of the interesting region, in the middle of the patch
// and half way up the model (assuming there is one)
@ -526,18 +530,29 @@ void ActorViewer::Render()
camera.m_Orientation.Translate(centre.X, centre.Y, centre.Z);
camera.UpdateFrustum();
g_Renderer.GetSceneRenderer().SetSceneCamera(camera, camera);
sceneRenderer.SetSceneCamera(camera, camera);
g_Renderer.BeginFrame();
g_Renderer.GetSceneRenderer().RenderScene(g_Renderer.GetDeviceCommandContext(), m);
Renderer::Backend::IDeviceCommandContext* deviceCommandContext =
g_Renderer.GetDeviceCommandContext();
sceneRenderer.PrepareScene(deviceCommandContext, m);
deviceCommandContext->BeginFramebufferPass(
deviceCommandContext->GetDevice()->GetCurrentBackbuffer());
sceneRenderer.RenderScene(deviceCommandContext);
sceneRenderer.RenderSceneOverlays(deviceCommandContext);
{
CCanvas2D canvas(g_xres, g_yres, g_VideoMode.GetScale(), g_Renderer.GetDeviceCommandContext());
CCanvas2D canvas(g_xres, g_yres, g_VideoMode.GetScale(), deviceCommandContext);
g_Logger->Render(canvas);
g_ProfileViewer.RenderProfile(canvas);
}
deviceCommandContext->EndFramebufferPass();
g_Renderer.EndFrame();
}