Skip to content

Commit

Permalink
Fix FSAA in UI and lower VRAM consumption (#313)
Browse files Browse the repository at this point in the history
* Fix FSAA in UI and lower VRAM consumption

FSAA was being requested however due to how the compositor was setup,
this effect was not taking effect.

Additionally, the Compositor setup was improved to lower memory
consumption. Originally the setup was taken from Ogre samples which
assume they will ultimately be rendering to a window.

However this is not the case and thus IGN was creating 3 render targets
(two for ping-ponging between postprocess FXs + one for storing the
final result)
This was optimized so that we only create 2 render targets: two for
ping-ponging between postprocess FXs and we pick at runtime which one is
storing the final result via the new variable renderTargetResultsIdx

Further performance optimizations could be made in Ogre 2.2 to improve
unnecessary MSAA resolving when doing postprocess, though considering
there's currently only one postprocessing effect (the Gaussian filter) I
doubt this optimization would make much of a difference

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Add Ogre2RenderTarget::RenderTarget back

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Rewrote the compositor changes to support RenderWindows

As a bonus this new method breaks ABI far less.
Fix leak: DestroyCompositor would often not be called

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Mantain ABI compatibility #Ogre2IsRenderWindowABI

When merging to newer branches that can break the ABI,
revert this commit

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Fix ABI problems

I gave up on commit undoing

It's clear that on the next release, Ogre2RenderTarget and
Ogre2RenderTexture need to be merged together.

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Fix camel case convention

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Make Ogre2RenderTarget::RenderTarget pure virtual again

Hopefully this will prevent ABI breakage

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Fix deprecation warnings during build

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

* Fix invalid write of size 8

This was causing heap corruption. At best it would crash. At worst it
would manifeset in subtle weird behaviors

Signed-off-by: Matias N. Goldberg <dark_sylinc@yahoo.com.ar>

Co-authored-by: Ian Chen <ichen@osrfoundation.org>
  • Loading branch information
darksylinc and iche033 authored Jun 14, 2021
1 parent 1421901 commit b29c295
Show file tree
Hide file tree
Showing 5 changed files with 410 additions and 168 deletions.
73 changes: 67 additions & 6 deletions ogre2/include/ignition/rendering/ogre2/Ogre2RenderTarget.hh
Original file line number Diff line number Diff line change
Expand Up @@ -115,9 +115,31 @@ namespace ignition
/// \see Camera::SetShadowsNodeDefDirty
public: void SetShadowsNodeDefDirty();

/// \brief Get a pointer to the ogre render target
/// \brief Get a pointer to the ogre render target containing
/// the results of the render (implemented separately
/// to avoid breaking ABI of the pure virtual function)
protected: Ogre::RenderTarget *RenderTargetImpl() const;

/// \brief Get a pointer to the ogre render target containing
/// the results of the render
public: virtual Ogre::RenderTarget *RenderTarget() const = 0;

/// \brief Returns true if this is a render window
/// TODO(anyone): this function should be virtual.
/// We didn't do it to preserve ABI.
/// Look in commit history for '#Ogre2IsRenderWindowABI' to
/// see changes made and revert
public: bool IsRenderWindow() const;

// Documentation inherited
public: unsigned int GLIdImpl() const;

/// \brief Destroy the render texture
protected: void DestroyTargetImpl();

/// \brief Build the render texture
protected: void BuildTargetImpl();

/// \brief Get visibility mask for the viewport associated with this
/// render target
/// \return Visibility mask
Expand All @@ -128,12 +150,23 @@ namespace ignition
/// \param[in] _mask Visibility mask
public: virtual void SetVisibilityMask(uint32_t _mask);

/// \brief Deprecated. Use other overloads.
public: static IGN_DEPRECATED(5) void UpdateRenderPassChain(
Ogre::CompositorWorkspace *_workspace,
const std::string &_workspaceDefName,
const std::string &_baseNode, const std::string &_finalNode,
const std::vector<RenderPassPtr> &_renderPasses,
bool _recreateNodes);

/// \brief Update the render pass chain
public: static void UpdateRenderPassChain(
Ogre::CompositorWorkspace *_workspace,
const std::string &_workspaceDefName,
const std::string &_baseNode, const std::string &_finalNode,
const std::vector<RenderPassPtr> &_renderPasses, bool _recreateNodes);
const std::vector<RenderPassPtr> &_renderPasses,
bool _recreateNodes,
Ogre::Texture *(*_ogreTextures)[2],
bool _isRenderWindow);

/// \brief Update the background color
protected: virtual void UpdateBackgroundColor();
Expand Down Expand Up @@ -168,6 +201,10 @@ namespace ignition
/// \sa BaseRenderTarget::Rebuild()
protected: void RebuildMaterial();

/// Calls Ogre2RenderTexture::SetOgreTexture if appropiate to ensure
/// Ogre2RenderTexture::ogreTexture always has our outputs
protected: void SyncOgreTextureVars();

/// \brief Pointer to the internal ogre camera
protected: Ogre::Camera *ogreCamera = nullptr;

Expand All @@ -187,7 +224,11 @@ namespace ignition
/// \brief a material used by for the render target
protected: MaterialPtr material;

/// \brief Helper class that applies the material to the render target
/// \brief Unused. Kept for ABI reasons.
///
/// Just in case we set this value to
/// Ogre2RenderTargetPrivate::materialApplicator[0] which is what
/// most client applications may want.
protected: Ogre2RenderTargetMaterialPtr materialApplicator;

/// \brief Flag to indicate if the render target color has changed
Expand Down Expand Up @@ -229,7 +270,9 @@ namespace ignition
// Documentation inherited
public: virtual unsigned int GLId() const override;

// Documentation inherited.
// Documentation inherited
// TODO(anyone): this function should be removed.
// We didn't do it to preserve ABI.
public: virtual Ogre::RenderTarget *RenderTarget() const override;

// Documentation inherited.
Expand All @@ -241,8 +284,20 @@ namespace ignition
/// \brief Build the render texture
protected: virtual void BuildTarget();

/// \brief Pointer to the internal ogre render texture object
protected: Ogre::Texture *ogreTexture = nullptr;
/// \brief Do not call this function directly.
///
/// It's used to keep ABI compatibility to sync ogreTexture
/// with the internal pointer from our base class.
/// \param[in] _ogreTexture texture from
/// Ogre2RenderTargetPrivate::ogreTexture[1]
public: void SetOgreTexture(Ogre::Texture *_ogreTexture);

/// \brief Unused. Kept for ABI reasons.
///
/// Just in case we set this value to
/// Ogre2RenderTargetPrivate::ogreTexture[1] which is what most client
/// applications may want.
protected: IGN_DEPRECATED(5) Ogre::Texture * ogreTexture = nullptr;

/// \brief Make scene our friend so it can create a ogre2 render texture
private: friend class Ogre2Scene;
Expand All @@ -261,6 +316,12 @@ namespace ignition
// Documentation inherited.
public: virtual void Destroy() override;

// TODO(anyone): this function should be virtual.
// We didn't do it to preserve ABI.
// Looks in commit history for '#Ogre2IsRenderWindowABI' to
// see changes made and revert
public: bool IsRenderWindow() const;

// Documentation inherited.
public: virtual Ogre::RenderTarget *RenderTarget() const override;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ namespace ignition
Ogre::Material *_originalMaterial, uint16_t _lodIndex,
const Ogre::Renderable *_rend) override;

/// \brief Returns this->renderTarget == _renderTarget
public: bool IsSameRenderTarget(Ogre::RenderTarget *_renderTarget);

/// \brief scene manager responsible for rendering
private: Ogre::SceneManager *scene = nullptr;

Expand Down
114 changes: 58 additions & 56 deletions ogre2/src/Ogre2DepthCamera.cc
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ class ignition::rendering::Ogre2DepthCameraPrivate
public: Ogre::CompositorWorkspace *ogreCompositorWorkspace = nullptr;

/// \brief Output texture with depth and color data
public: Ogre::TexturePtr ogreDepthTexture;
public: Ogre::TexturePtr ogreDepthTexture[2];

/// \brief Dummy render texture for the depth data
public: RenderTexturePtr depthTexture;
Expand Down Expand Up @@ -297,10 +297,13 @@ void Ogre2DepthCamera::Destroy()
Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2();

// remove depth texture, material, compositor
if (this->dataPtr->ogreDepthTexture)
for( size_t i = 0u; i < 2u; ++i )
{
Ogre::TextureManager::getSingleton().remove(
this->dataPtr->ogreDepthTexture->getName());
if (this->dataPtr->ogreDepthTexture[i])
{
Ogre::TextureManager::getSingleton().remove(
this->dataPtr->ogreDepthTexture[i]->getName());
}
}
if (this->dataPtr->ogreCompositorWorkspace)
{
Expand Down Expand Up @@ -588,41 +591,11 @@ void Ogre2DepthCamera::CreateDepthTexture()
this->dataPtr->ogreCompositorBaseNodeDef = baseNodeDefName;
Ogre::CompositorNodeDef *baseNodeDef =
ogreCompMgr->addNodeDefinition(baseNodeDefName);
Ogre::TextureDefinitionBase::TextureDefinition *rt0TexDef =
baseNodeDef->addTextureDefinition("rt0");
rt0TexDef->textureType = Ogre::TEX_TYPE_2D;
rt0TexDef->width = 0;
rt0TexDef->height = 0;
rt0TexDef->depth = 1;
rt0TexDef->numMipmaps = 0;
rt0TexDef->widthFactor = 1;
rt0TexDef->heightFactor = 1;
rt0TexDef->formatList = {Ogre::PF_FLOAT32_RGBA};
rt0TexDef->fsaa = 0;
rt0TexDef->uav = false;
rt0TexDef->automipmaps = false;
rt0TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse;
rt0TexDef->depthBufferId = Ogre::DepthBuffer::POOL_INVALID;
rt0TexDef->depthBufferFormat = Ogre::PF_UNKNOWN;
rt0TexDef->fsaaExplicitResolve = false;

Ogre::TextureDefinitionBase::TextureDefinition *rt1TexDef =
baseNodeDef->addTextureDefinition("rt1");
rt1TexDef->textureType = Ogre::TEX_TYPE_2D;
rt1TexDef->width = 0;
rt1TexDef->height = 0;
rt1TexDef->depth = 1;
rt1TexDef->numMipmaps = 0;
rt1TexDef->widthFactor = 1;
rt1TexDef->heightFactor = 1;
rt1TexDef->formatList = {Ogre::PF_FLOAT32_RGBA};
rt1TexDef->fsaa = 0;
rt1TexDef->uav = false;
rt1TexDef->automipmaps = false;
rt1TexDef->hwGammaWrite = Ogre::TextureDefinitionBase::BoolFalse;
rt1TexDef->depthBufferId = Ogre::DepthBuffer::POOL_INVALID;
rt1TexDef->depthBufferFormat = Ogre::PF_UNKNOWN;
rt1TexDef->fsaaExplicitResolve = false;

baseNodeDef->addTextureSourceName(
"rt0", 0u, Ogre::TextureDefinitionBase::TEXTURE_INPUT);
baseNodeDef->addTextureSourceName(
"rt1", 1u, Ogre::TextureDefinitionBase::TEXTURE_INPUT);

Ogre::TextureDefinitionBase::TextureDefinition *depthTexDef =
baseNodeDef->addTextureDefinition("depthTexture");
Expand Down Expand Up @@ -853,10 +826,10 @@ void Ogre2DepthCamera::CreateDepthTexture()
Ogre::CompositorNodeDef *finalNodeDef =
ogreCompMgr->addNodeDefinition(finalNodeDefName);

// output texture
finalNodeDef->addTextureSourceName("rt_output", 0,
finalNodeDef->addTextureSourceName("rt_input", 0,
Ogre::TextureDefinitionBase::TEXTURE_INPUT);
finalNodeDef->addTextureSourceName("rt_input", 1,
// output texture
finalNodeDef->addTextureSourceName("rt_output", 1,
Ogre::TextureDefinitionBase::TEXTURE_INPUT);

finalNodeDef->setNumTargetPass(1);
Expand Down Expand Up @@ -892,8 +865,9 @@ void Ogre2DepthCamera::CreateDepthTexture()
Ogre::CompositorWorkspaceDef *workDef =
ogreCompMgr->addWorkspaceDefinition(wsDefName);

workDef->connect(baseNodeDefName, 0, finalNodeDefName, 1);
workDef->connectExternal(0, finalNodeDefName, 0);
workDef->connectExternal(0, baseNodeDefName, 0);
workDef->connectExternal(1, baseNodeDefName, 1);
workDef->connect(baseNodeDefName, finalNodeDefName);
}
Ogre::CompositorWorkspaceDef *wsDef =
ogreCompMgr->getWorkspaceDefinition(wsDefName);
Expand All @@ -905,12 +879,19 @@ void Ogre2DepthCamera::CreateDepthTexture()
}

// create render texture - these textures pack the range data
this->dataPtr->ogreDepthTexture =
Ogre::TextureManager::getSingleton().createManual(
this->Name() + "_depth", "General", Ogre::TEX_TYPE_2D,
this->ImageWidth(), this->ImageHeight(), 1, 0,
Ogre::PF_FLOAT32_RGBA, Ogre::TU_RENDERTARGET,
0, false, 0, Ogre::BLANKSTRING, false, true);
for( size_t i = 0u; i < 2u; ++i )
{
this->dataPtr->ogreDepthTexture[i] =
Ogre::TextureManager::getSingleton().createManual(
this->Name() + "_depth" + std::to_string(i), "General",
Ogre::TEX_TYPE_2D, this->ImageWidth(), this->ImageHeight(), 1, 0,
Ogre::PF_FLOAT32_RGBA, Ogre::TU_RENDERTARGET,
0, false, 0, Ogre::BLANKSTRING, false, true);

Ogre::RenderTarget *rt =
this->dataPtr->ogreDepthTexture[i]->getBuffer()->getRenderTarget();
rt->setDepthBufferPool(Ogre::DepthBuffer::POOL_INVALID);
}

CreateWorkspaceInstance();
}
Expand All @@ -922,13 +903,19 @@ void Ogre2DepthCamera::CreateWorkspaceInstance()
auto ogreRoot = engine->OgreRoot();
Ogre::CompositorManager2 *ogreCompMgr = ogreRoot->getCompositorManager2();

Ogre::RenderTarget *rt =
this->dataPtr->ogreDepthTexture->getBuffer()->getRenderTarget();
Ogre::CompositorChannelVec externalTargets(2u);
for( size_t i = 0u; i < 2u; ++i )
{
externalTargets[i].target =
this->dataPtr->ogreDepthTexture[i]->getBuffer()->getRenderTarget();
externalTargets[i].textures.push_back(this->dataPtr->ogreDepthTexture[i]);
}

// create compositor worksspace
this->dataPtr->ogreCompositorWorkspace =
ogreCompMgr->addWorkspace(this->scene->OgreSceneManager(),
rt, this->ogreCamera, this->dataPtr->ogreCompositorWorkspaceDef, false);
externalTargets, this->ogreCamera,
this->dataPtr->ogreCompositorWorkspaceDef, false);

// add the listener
Ogre::CompositorNode *node =
Expand Down Expand Up @@ -963,20 +950,35 @@ void Ogre2DepthCamera::Render()
//////////////////////////////////////////////////
void Ogre2DepthCamera::PreRender()
{
if (!this->dataPtr->ogreDepthTexture)
if (!this->dataPtr->ogreDepthTexture[0])
this->CreateDepthTexture();

if (!this->dataPtr->ogreCompositorWorkspace)
this->CreateWorkspaceInstance();

Ogre::Texture *rawDepthTextures[2] =
{
this->dataPtr->ogreDepthTexture[0].get(),
this->dataPtr->ogreDepthTexture[1].get()
};

// update depth camera render passes
Ogre2RenderTarget::UpdateRenderPassChain(
this->dataPtr->ogreCompositorWorkspace,
this->dataPtr->ogreCompositorWorkspaceDef,
this->dataPtr->ogreCompositorBaseNodeDef,
this->dataPtr->ogreCompositorFinalNodeDef,
this->dataPtr->renderPasses,
this->dataPtr->renderPassDirty);
this->dataPtr->renderPassDirty,
&rawDepthTextures,
false);

if (rawDepthTextures[0] != this->dataPtr->ogreDepthTexture[0].get())
{
std::swap( this->dataPtr->ogreDepthTexture[0],
this->dataPtr->ogreDepthTexture[1] );
}

for (auto &pass : this->dataPtr->renderPasses)
pass->PreRender();

Expand Down Expand Up @@ -1028,7 +1030,7 @@ void Ogre2DepthCamera::PostRender()
1, imageFormat, this->dataPtr->depthBuffer);

// blit data from gpu to cpu
auto rt = this->dataPtr->ogreDepthTexture->getBuffer()->getRenderTarget();
auto rt = this->dataPtr->ogreDepthTexture[1]->getBuffer()->getRenderTarget();
rt->copyContentsToMemory(dstBox, Ogre::RenderTarget::FB_AUTO);

if (!this->dataPtr->depthImage)
Expand Down
Loading

0 comments on commit b29c295

Please sign in to comment.