Add render target manager, issue #47

This commit is contained in:
kaetemi 2014-07-31 00:46:00 +02:00
parent 5de85eb194
commit 64666c302a
7 changed files with 285 additions and 19 deletions

View file

@ -34,7 +34,7 @@
#include "nel/3d/vertex_stream_manager.h" #include "nel/3d/vertex_stream_manager.h"
#include "nel/3d/async_texture_manager.h" #include "nel/3d/async_texture_manager.h"
#include "nel/3d/lod_character_manager.h" #include "nel/3d/lod_character_manager.h"
#include "nel/3d/render_target_manager.h"
namespace NL3D namespace NL3D
{ {
@ -71,6 +71,7 @@ protected:
bool _WindowInit; bool _WindowInit;
CMatrixContext _CurrentMatrixContext; CMatrixContext _CurrentMatrixContext;
CFontManager _FontManager; CFontManager _FontManager;
CRenderTargetManager _RenderTargetManager;
// Components List. // Components List.
typedef CPtrSet<CTextureUser> TTextureSet; typedef CPtrSet<CTextureUser> TTextureSet;
typedef CPtrSet<CTextContextUser> TTextContextSet; typedef CPtrSet<CTextContextUser> TTextContextSet;
@ -253,6 +254,8 @@ public:
/// get cahce information. /// get cahce information.
virtual std::string getFontManagerCacheInformation() const ; virtual std::string getFontManagerCacheInformation() const ;
virtual CRenderTargetManager &getRenderTargetManager() { return _RenderTargetManager; }
/** Create a new texture file, searching in CPath. /** Create a new texture file, searching in CPath.
* \param file filename, local to CPath paths. * \param file filename, local to CPath paths.

View file

@ -0,0 +1,83 @@
/**
* \file render_target_manager.h
* \brief CRenderTargetManager
* \date 2014-07-30 21:30GMT
* \author Jan Boon (Kaetemi)
* CRenderTargetManager
*/
/*
* Copyright (C) 2013 by authors
*
* This file is part of NL3D.
* NL3D is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* NL3D is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
* Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with NL3D. If not, see
* <http://www.gnu.org/licenses/>.
*/
#ifndef NL3D_RENDER_TARGET_MANAGER_H
#define NL3D_RENDER_TARGET_MANAGER_H
#include <nel/misc/types_nl.h>
// STL includes
// NeL includes
#include <nel/misc/smart_ptr.h>
#include <nel/misc/geom_ext.h>
// Project includes
// ...
namespace NL3D {
class UDriver;
class ITexture;
class CTextureUser;
class CDriverUser;
struct CRenderTargetDescInt;
/**
* \brief CRenderTargetManager
* \date 2013-07-03 20:17GMT
* \author Jan Boon (Kaetemi)
* CRenderTargetManager
* Usage: Call 'getRenderTarget' when you start using a render target,
* call 'recycledRenderTarget' when the render target can be recycled.
* At end of frame call cleanup.
* Assumes semi-constant render target quantity between frames,
* except on changes of resolution or feature settings.
*/
class CRenderTargetManager
{
public:
CRenderTargetManager();
~CRenderTargetManager();
NL3D::CTextureUser *getRenderTarget(uint width, uint height);
void recycleRenderTarget(NL3D::CTextureUser *renderTarget);
void cleanup();
private:
friend class CDriverUser;
NL3D::UDriver *m_Driver;
std::vector<CRenderTargetDescInt *> m_RenderTargets;
}; /* class CRenderTargetManager */
} /* namespace NL3D */
#endif /* #ifndef NL3D_RENDER_TARGET_MANAGER_H */
/* end of file */

View file

@ -65,10 +65,12 @@ public:
/// Sets driver and generates necessary render targets /// Sets driver and generates necessary render targets
virtual void setDriver(NL3D::UDriver *driver); virtual void setDriver(NL3D::UDriver *driver);
void releaseTextures(); /*void releaseTextures();
void initTextures(); void initTextures();
void setTextures(); void setTextures();
void verifyTextures(); void verifyTextures();*/
void getTextures();
void recycleTextures();
/// Gets the required screen resolution for this device /// Gets the required screen resolution for this device
virtual bool getScreenResolution(uint &width, uint &height); virtual bool getScreenResolution(uint &width, uint &height);
@ -116,9 +118,7 @@ private:
CFrustum m_Frustum[NL_STEREO_MAX_USER_CAMERAS]; CFrustum m_Frustum[NL_STEREO_MAX_USER_CAMERAS];
CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS]; CMatrix m_CameraMatrix[NL_STEREO_MAX_USER_CAMERAS];
NLMISC::CSmartPtr<NL3D::ITexture> m_LeftTex;
NL3D::CTextureUser *m_LeftTexU; NL3D::CTextureUser *m_LeftTexU;
NLMISC::CSmartPtr<NL3D::ITexture> m_RightTex;
NL3D::CTextureUser *m_RightTexU; NL3D::CTextureUser *m_RightTexU;
NL3D::UMaterial m_Mat; NL3D::UMaterial m_Mat;
NLMISC::CQuadUV m_QuadUV; NLMISC::CQuadUV m_QuadUV;

View file

@ -63,6 +63,7 @@ class U3dMouseListener;
class ULight; class ULight;
class UAnimationSet; class UAnimationSet;
class UWaterEnvMap; class UWaterEnvMap;
class CRenderTargetManager;
typedef void (*emptyProc)(void); typedef void (*emptyProc)(void);
@ -322,6 +323,8 @@ public:
/// get cahce information. /// get cahce information.
virtual std::string getFontManagerCacheInformation() const =0; virtual std::string getFontManagerCacheInformation() const =0;
virtual CRenderTargetManager &getRenderTargetManager() =0;
/** Create a new texture file, searching in CPath. NB: by default a textureFile created with this /** Create a new texture file, searching in CPath. NB: by default a textureFile created with this
* method has a setAllowDegradation() at false. * method has a setAllowDegradation() at false.

View file

@ -192,6 +192,7 @@ CDriverUser::CDriverUser (uintptr_t windowIcon, TDriver driver, emptyProc exitFu
_PBTri.lock (iba); _PBTri.lock (iba);
iba.setTri(0, 0, 1, 2); iba.setTri(0, 0, 1, 2);
_RenderTargetManager.m_Driver = this;
_ShapeBank._DriverUser = this; _ShapeBank._DriverUser = this;
NL_SET_IB_NAME(_PBLine, "CDriverUser::_PBLine"); NL_SET_IB_NAME(_PBLine, "CDriverUser::_PBLine");
@ -1357,6 +1358,7 @@ void CDriverUser::swapBuffers()
NL3D_HAUTO_SWAP_DRIVER; NL3D_HAUTO_SWAP_DRIVER;
_Driver->swapBuffers(); _Driver->swapBuffers();
_RenderTargetManager.cleanup();
} }
// *************************************************************************** // ***************************************************************************

View file

@ -0,0 +1,152 @@
/**
* \file render_target_manager.cpp
* \brief CRenderTargetManager
* \date 2014-07-30 21:30GMT
* \author Jan Boon (Kaetemi)
* CRenderTargetManager
*/
/*
* Copyright (C) 2014 by authors
*
* This file is part of NL3D.
* NL3D is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* NL3D is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General
* Public License for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with NL3D. If not, see
* <http://www.gnu.org/licenses/>.
*/
#include <nel/misc/types_nl.h>
#include <nel/3d/render_target_manager.h>
// STL includes
#include <sstream>
// NeL includes
// #include <nel/misc/debug.h>
#include <nel/3d/u_camera.h>
#include <nel/3d/u_driver.h>
#include <nel/3d/material.h>
#include <nel/3d/texture_bloom.h>
#include <nel/3d/texture_user.h>
#include <nel/3d/driver_user.h>
#include <nel/3d/u_texture.h>
// Project includes
using namespace std;
// using namespace NLMISC;
namespace NL3D {
struct CRenderTargetDescInt
{
public:
uint Width;
uint Height;
NL3D::CTextureUser *TextureUser;
NLMISC::CSmartPtr<NL3D::ITexture> TextureInterface;
bool InUse;
bool Used;
};
CRenderTargetManager::CRenderTargetManager() : m_Driver(NULL)
{
}
CRenderTargetManager::~CRenderTargetManager()
{
// Call twice to reset counters and cleanup
cleanup();
cleanup();
}
NL3D::CTextureUser *CRenderTargetManager::getRenderTarget(uint width, uint height)
{
// Find or create a render target, short loop so no real optimization
for (std::vector<CRenderTargetDescInt *>::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it)
{
CRenderTargetDescInt *desc = *it;
if (!desc->InUse && desc->Width == width && desc->Height == height)
{
desc->InUse = true;
desc->Used = true;
return desc->TextureUser;
}
}
nldebug("3D: Create new render target (%u x %u)", width, height);
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
CRenderTargetDescInt *desc = new CRenderTargetDescInt();
desc->TextureInterface = new CTextureBloom(); // LOL
desc->TextureInterface->setRenderTarget(true);
desc->TextureInterface->setReleasable(false);
desc->TextureInterface->resize(width, height);
desc->TextureInterface->setFilterMode(ITexture::Linear, ITexture::LinearMipMapOff);
desc->TextureInterface->setWrapS(ITexture::Clamp);
desc->TextureInterface->setWrapT(ITexture::Clamp);
drvInternal->setupTexture(*desc->TextureInterface);
desc->TextureUser = new CTextureUser(desc->TextureInterface);
nlassert(!drvInternal->isTextureRectangle(desc->TextureInterface)); // Not allowed, we only support NPOT for render targets now.
desc->Width = width;
desc->Height = height;
desc->Used = true;
desc->InUse = true;
m_RenderTargets.push_back(desc);
return desc->TextureUser;
}
void CRenderTargetManager::recycleRenderTarget(NL3D::CTextureUser *renderTarget)
{
for (std::vector<CRenderTargetDescInt *>::iterator it(m_RenderTargets.begin()), end(m_RenderTargets.end()); it != end; ++it)
{
CRenderTargetDescInt *desc = *it;
if (desc->TextureUser == renderTarget)
{
desc->InUse = false;
return;
}
}
nlerror("3D: Render target not found");
}
void CRenderTargetManager::cleanup()
{
for (sint i = 0; i < (sint)m_RenderTargets.size(); ++i)
{
CRenderTargetDescInt *desc = m_RenderTargets[i];
nlassert(!desc->InUse); // Assert for debugging, to not allow textures being carried over between frames. Optional assert
if (!desc->InUse)
{
if (!desc->Used)
{
// No longer in use
nldebug("3D: Release render target (%u x %u)", desc->Width, desc->Height);
delete desc->TextureUser;
desc->TextureUser = NULL;
desc->TextureInterface = NULL; // CSmartPtr
m_RenderTargets.erase(m_RenderTargets.begin() + i);
--i;
}
else
{
// Flag for next round
desc->Used = false;
}
}
}
}
} /* namespace NL3D */
/* end of file */

View file

@ -42,6 +42,7 @@
#include <nel/3d/texture_user.h> #include <nel/3d/texture_user.h>
#include <nel/3d/driver_user.h> #include <nel/3d/driver_user.h>
#include <nel/3d/u_texture.h> #include <nel/3d/u_texture.h>
#include <nel/3d/render_target_manager.h>
using namespace std; using namespace std;
// using namespace NLMISC; // using namespace NLMISC;
@ -137,8 +138,6 @@ CStereoDebugger::CStereoDebugger() : m_Driver(NULL), m_Stage(0), m_SubStage(0),
CStereoDebugger::~CStereoDebugger() CStereoDebugger::~CStereoDebugger()
{ {
releaseTextures();
if (!m_Mat.empty()) if (!m_Mat.empty())
{ {
m_Driver->deleteMaterial(m_Mat); m_Driver->deleteMaterial(m_Mat);
@ -188,8 +187,6 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver)
if (m_PixelProgram) if (m_PixelProgram)
{ {
initTextures();
m_Mat = m_Driver->createMaterial(); m_Mat = m_Driver->createMaterial();
m_Mat.initUnlit(); m_Mat.initUnlit();
m_Mat.setColor(CRGBA::White); m_Mat.setColor(CRGBA::White);
@ -202,8 +199,6 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver)
mat->setZFunc(CMaterial::always); mat->setZFunc(CMaterial::always);
mat->setDoubleSided(true); mat->setDoubleSided(true);
setTextures();
m_QuadUV.V0 = CVector(0.f, 0.f, 0.5f); m_QuadUV.V0 = CVector(0.f, 0.f, 0.5f);
m_QuadUV.V1 = CVector(1.f, 0.f, 0.5f); m_QuadUV.V1 = CVector(1.f, 0.f, 0.5f);
m_QuadUV.V2 = CVector(1.f, 1.f, 0.5f); m_QuadUV.V2 = CVector(1.f, 1.f, 0.5f);
@ -216,6 +211,32 @@ void CStereoDebugger::setDriver(NL3D::UDriver *driver)
} }
} }
void CStereoDebugger::getTextures()
{
nlassert(!m_LeftTexU);
nlassert(!m_RightTexU);
uint32 width, height;
m_Driver->getWindowSize(width, height);
m_LeftTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
m_RightTexU = m_Driver->getRenderTargetManager().getRenderTarget(width, height);
NL3D::CMaterial *mat = m_Mat.getObjectPtr();
mat->setTexture(0, m_LeftTexU->getITexture());
mat->setTexture(1, m_RightTexU->getITexture());
}
void CStereoDebugger::recycleTextures()
{
nlassert(m_LeftTexU);
nlassert(m_RightTexU);
m_Mat.getObjectPtr()->setTexture(0, NULL);
m_Mat.getObjectPtr()->setTexture(1, NULL);
m_Driver->getRenderTargetManager().recycleRenderTarget(m_LeftTexU);
m_Driver->getRenderTargetManager().recycleRenderTarget(m_RightTexU);
m_LeftTexU = NULL;
m_RightTexU = NULL;
}
/*
void CStereoDebugger::releaseTextures() void CStereoDebugger::releaseTextures()
{ {
if (!m_Mat.empty()) if (!m_Mat.empty())
@ -233,7 +254,7 @@ void CStereoDebugger::releaseTextures()
m_RightTexU = NULL; m_RightTexU = NULL;
m_RightTex = NULL; // CSmartPtr m_RightTex = NULL; // CSmartPtr
} }
*//*
void CStereoDebugger::initTextures() void CStereoDebugger::initTextures()
{ {
uint32 width, height; uint32 width, height;
@ -261,15 +282,15 @@ void CStereoDebugger::initTextures()
drvInternal->setupTexture(*m_RightTex); drvInternal->setupTexture(*m_RightTex);
m_RightTexU = new CTextureUser(m_RightTex); m_RightTexU = new CTextureUser(m_RightTex);
nlassert(!drvInternal->isTextureRectangle(m_RightTex)); // not allowed nlassert(!drvInternal->isTextureRectangle(m_RightTex)); // not allowed
} }*/
/*
void CStereoDebugger::setTextures() void CStereoDebugger::setTextures()
{ {
NL3D::CMaterial *mat = m_Mat.getObjectPtr(); NL3D::CMaterial *mat = m_Mat.getObjectPtr();
mat->setTexture(0, m_LeftTex); mat->setTexture(0, m_LeftTex);
mat->setTexture(1, m_RightTex); mat->setTexture(1, m_RightTex);
} }*/
/*
void CStereoDebugger::verifyTextures() void CStereoDebugger::verifyTextures()
{ {
if (m_Driver) if (m_Driver)
@ -287,7 +308,7 @@ void CStereoDebugger::verifyTextures()
setTextures(); setTextures();
} }
} }
} }*/
/// Gets the required screen resolution for this device /// Gets the required screen resolution for this device
bool CStereoDebugger::getScreenResolution(uint &width, uint &height) bool CStereoDebugger::getScreenResolution(uint &width, uint &height)
@ -407,6 +428,7 @@ bool CStereoDebugger::beginRenderTarget()
{ {
if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled)) if (m_Stage != 3 && m_Driver && (m_Driver->getPolygonMode() == UDriver::Filled))
{ {
if (!m_LeftTexU) getTextures();
if (m_Stage % 2) static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_RightTexU, 0, 0, 0, 0); if (m_Stage % 2) static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_RightTexU, 0, 0, 0, 0);
else static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_LeftTexU, 0, 0, 0, 0); else static_cast<CDriverUser *>(m_Driver)->setRenderTarget(*m_LeftTexU, 0, 0, 0, 0);
return true; return true;
@ -430,14 +452,15 @@ bool CStereoDebugger::endRenderTarget()
uint32 width, height; uint32 width, height;
NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver(); NL3D::IDriver *drvInternal = (static_cast<CDriverUser *>(m_Driver))->getDriver();
NL3D::CMaterial *mat = m_Mat.getObjectPtr(); NL3D::CMaterial *mat = m_Mat.getObjectPtr();
mat->setTexture(0, m_LeftTex); mat->setTexture(0, m_LeftTexU->getITexture());
mat->setTexture(1, m_RightTex); mat->setTexture(1, m_RightTexU->getITexture());
drvInternal->activePixelProgram(m_PixelProgram); drvInternal->activePixelProgram(m_PixelProgram);
m_Driver->drawQuad(m_QuadUV, m_Mat); m_Driver->drawQuad(m_QuadUV, m_Mat);
drvInternal->activePixelProgram(NULL); drvInternal->activePixelProgram(NULL);
m_Driver->enableFog(fogEnabled); m_Driver->enableFog(fogEnabled);
recycleTextures();
return true; return true;
} }