GL: Share depth and stencil to get similar behaviour to D3D driver

This commit is contained in:
kaetemi 2014-08-03 18:59:19 +02:00
parent 54f4d5bac3
commit f9aa0bf7cc
3 changed files with 101 additions and 65 deletions

View file

@ -1032,6 +1032,8 @@ bool CDriverGL::release()
// Call IDriver::release() before, to destroy textures, shaders and VBs... // Call IDriver::release() before, to destroy textures, shaders and VBs...
IDriver::release(); IDriver::release();
nlassert(_DepthStencilFBOs.empty());
_SwapBufferCounter = 0; _SwapBufferCounter = 0;
// delete querries // delete querries

View file

@ -146,6 +146,23 @@ public:
virtual uint getVisibleCount(); virtual uint getVisibleCount();
}; };
// ***************************************************************************
class CDepthStencilFBO : public NLMISC::CRefCount
{
public:
CDepthStencilFBO(CDriverGL *driver, uint width, uint height);
~CDepthStencilFBO();
uint Width;
uint Height;
GLuint DepthFBOId;
GLuint StencilFBOId;
private:
CDriverGL *m_Driver;
};
// *************************************************************************** // ***************************************************************************
class CTextureDrvInfosGL : public ITextureDrvInfos class CTextureDrvInfosGL : public ITextureDrvInfos
{ {
@ -173,12 +190,9 @@ public:
GLuint FBOId; GLuint FBOId;
// depth stencil FBO id // depth stencil FBO id
GLuint DepthFBOId;
GLuint StencilFBOId;
bool InitFBO;
bool AttachDepthStencil; bool AttachDepthStencil;
bool UsePackedDepthStencil; NLMISC::CSmartPtr<CDepthStencilFBO> DepthStencilFBO;
bool InitFBO;
// The current wrap modes assigned to the texture. // The current wrap modes assigned to the texture.
ITexture::TWrapMode WrapS; ITexture::TWrapMode WrapS;
@ -685,6 +699,7 @@ private:
friend class CTextureDrvInfosGL; friend class CTextureDrvInfosGL;
friend class CVertexProgamDrvInfosGL; friend class CVertexProgamDrvInfosGL;
friend class CPixelProgamDrvInfosGL; friend class CPixelProgamDrvInfosGL;
friend class CDepthStencilFBO;
private: private:
// Version of the driver. Not the interface version!! Increment when implementation of the driver change. // Version of the driver. Not the interface version!! Increment when implementation of the driver change.
@ -880,8 +895,11 @@ private:
// viewport before call to setRenderTarget, if BFO extension is supported // viewport before call to setRenderTarget, if BFO extension is supported
CViewport _OldViewport; CViewport _OldViewport;
// Current FBO render target
CSmartPtr<ITexture> _RenderTargetFBO; CSmartPtr<ITexture> _RenderTargetFBO;
// Share the same backbuffer for FBO render targets with window size
std::vector<CDepthStencilFBO *> _DepthStencilFBOs;
// Num lights return by GL_MAX_LIGHTS // Num lights return by GL_MAX_LIGHTS
uint _MaxDriverLight; uint _MaxDriverLight;

View file

@ -73,12 +73,8 @@ CTextureDrvInfosGL::CTextureDrvInfosGL(IDriver *drv, ItTexDrvInfoPtrMap it, CDri
#endif #endif
FBOId = 0; FBOId = 0;
DepthFBOId = 0;
StencilFBOId = 0;
InitFBO = false; InitFBO = false;
AttachDepthStencil = true; AttachDepthStencil = true;
UsePackedDepthStencil = drvGl->supportPackedDepthStencil();
TextureUsedIdx = 0; TextureUsedIdx = 0;
} }
@ -98,9 +94,9 @@ CTextureDrvInfosGL::~CTextureDrvInfosGL()
_Driver->_TextureUsed[TextureUsedIdx] = NULL; _Driver->_TextureUsed[TextureUsedIdx] = NULL;
} }
if(InitFBO)
{
#ifdef USE_OPENGLES #ifdef USE_OPENGLES
if (InitFBO)
{
nglDeleteFramebuffersOES(1, &FBOId); nglDeleteFramebuffersOES(1, &FBOId);
if(AttachDepthStencil) if(AttachDepthStencil)
{ {
@ -108,24 +104,73 @@ CTextureDrvInfosGL::~CTextureDrvInfosGL()
if(!UsePackedDepthStencil) if(!UsePackedDepthStencil)
nglDeleteRenderbuffersOES(1, &StencilFBOId); nglDeleteRenderbuffersOES(1, &StencilFBOId);
} }
#else }
nglDeleteFramebuffersEXT(1, &FBOId);
if(AttachDepthStencil)
{
nglDeleteRenderbuffersEXT(1, &DepthFBOId);
if(!UsePackedDepthStencil)
nglDeleteRenderbuffersEXT(1, &StencilFBOId);
}
#endif #endif
}
CDepthStencilFBO::CDepthStencilFBO(CDriverGL *driver, uint width, uint height)
{
nldebug("3D: Init shared FBO");
m_Driver = driver;
Width = width;
Height = height;
bool packedDepthStencil = driver->supportPackedDepthStencil();
nglGenRenderbuffersEXT(1, &DepthFBOId);
if (packedDepthStencil)
StencilFBOId = DepthFBOId;
else
nglGenRenderbuffersEXT(1, &StencilFBOId);
if (packedDepthStencil)
{
//nldebug("3D: using packed depth stencil");
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId);
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, width, height);
}
else
{
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthFBOId);
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, width, height);
/*
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId);
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, width, height);
*/
}
nlassert(DepthFBOId);
nlassert(StencilFBOId);
driver->_DepthStencilFBOs.push_back(this);
}
CDepthStencilFBO::~CDepthStencilFBO()
{
// driver remove
m_Driver->_DepthStencilFBOs.erase(std::find(m_Driver->_DepthStencilFBOs.begin(), m_Driver->_DepthStencilFBOs.end(), this));
if (DepthFBOId)
{
nldebug("3D: Release shared FBO");
nglDeleteRenderbuffersEXT(1, &DepthFBOId);
if (StencilFBOId == DepthFBOId)
StencilFBOId = 0;
DepthFBOId = 0;
}
if (StencilFBOId)
{
nglDeleteRenderbuffersEXT(1, &StencilFBOId);
StencilFBOId = 0;
} }
} }
// *************************************************************************** // ***************************************************************************
bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex) bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
{ {
if(!InitFBO) if (!InitFBO)
{ {
if(tex->isBloomTexture()) if (tex->isBloomTexture())
{ {
AttachDepthStencil = !((CTextureBloom*)tex)->isMode2D(); AttachDepthStencil = !((CTextureBloom*)tex)->isMode2D();
} }
@ -179,14 +224,6 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
#else #else
// generate IDs // generate IDs
nglGenFramebuffersEXT(1, &FBOId); nglGenFramebuffersEXT(1, &FBOId);
if(AttachDepthStencil)
{
nglGenRenderbuffersEXT(1, &DepthFBOId);
if(UsePackedDepthStencil)
StencilFBOId = DepthFBOId;
else
nglGenRenderbuffersEXT(1, &StencilFBOId);
}
//nldebug("3D: using depth %d and stencil %d", DepthFBOId, StencilFBOId); //nldebug("3D: using depth %d and stencil %d", DepthFBOId, StencilFBOId);
@ -194,34 +231,26 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId); nglBindFramebufferEXT(GL_FRAMEBUFFER_EXT, FBOId);
nglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, TextureMode, ID, 0); nglFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, TextureMode, ID, 0);
// attach depth/stencil render to FBO // attach depth stencil
// note: for some still unkown reason it's impossible to add if (AttachDepthStencil)
// a stencil buffer as shown in the respective docs (see
// opengl.org extension registry). Until a safe approach to add
// them is found, there will be no attached stencil for the time
// being, aside of using packed depth+stencil buffers.
if(AttachDepthStencil)
{ {
if(UsePackedDepthStencil) for (std::vector<CDepthStencilFBO *>::iterator it(_Driver->_DepthStencilFBOs.begin()), end(_Driver->_DepthStencilFBOs.end()); it != end; ++it)
{ {
//nldebug("3D: using packed depth stencil"); if ((*it)->Width == tex->getWidth() && (*it)->Height == tex->getHeight())
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId); {
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH24_STENCIL8_EXT, tex->getWidth(), tex->getHeight()); DepthStencilFBO = (*it);
break;
}
} }
else if (!DepthStencilFBO)
{ {
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, DepthFBOId); DepthStencilFBO = new CDepthStencilFBO(_Driver, tex->getWidth(), tex->getHeight());
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT24, tex->getWidth(), tex->getHeight());
/*
nglBindRenderbufferEXT(GL_RENDERBUFFER_EXT, StencilFBOId);
nglRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_STENCIL_INDEX8_EXT, tex->getWidth(), tex->getHeight());
*/
} }
nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, DepthFBOId); GL_RENDERBUFFER_EXT, DepthStencilFBO->DepthFBOId);
nldebug("3D: glFramebufferRenderbufferExt(depth:24) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); nldebug("3D: glFramebufferRenderbufferExt(depth:24) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT, nglFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_STENCIL_ATTACHMENT_EXT,
GL_RENDERBUFFER_EXT, StencilFBOId); GL_RENDERBUFFER_EXT, DepthStencilFBO->StencilFBOId);
nldebug("3D: glFramebufferRenderbufferExt(stencil:8) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT)); nldebug("3D: glFramebufferRenderbufferExt(stencil:8) = %X", nglCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT));
} }
#endif #endif
@ -339,17 +368,7 @@ bool CTextureDrvInfosGL::initFrameBufferObject(ITexture * tex)
#endif #endif
if (AttachDepthStencil) if (AttachDepthStencil)
{ {
#ifdef USE_OPENGLES DepthStencilFBO = NULL;
nglDeleteRenderbuffersOES(1, &DepthFBOId);
#else
nglDeleteRenderbuffersEXT(1, &DepthFBOId);
#endif
if(!UsePackedDepthStencil)
#ifdef USE_OPENGLES
nglDeleteRenderbuffersOES(1, &StencilFBOId);
#else
nglDeleteRenderbuffersEXT(1, &StencilFBOId);
#endif
} }
} }
@ -2260,11 +2279,8 @@ void CDriverGL::swapTextureHandle(ITexture &tex0, ITexture &tex1)
swap(t0->MinFilter, t1->MinFilter); swap(t0->MinFilter, t1->MinFilter);
swap(t0->TextureMode, t1->TextureMode); swap(t0->TextureMode, t1->TextureMode);
swap(t0->FBOId, t1->FBOId); swap(t0->FBOId, t1->FBOId);
swap(t0->DepthFBOId, t1->DepthFBOId); swap(t0->DepthStencilFBO, t1->DepthStencilFBO);
swap(t0->StencilFBOId, t1->StencilFBOId);
swap(t0->InitFBO, t1->InitFBO); swap(t0->InitFBO, t1->InitFBO);
swap(t0->AttachDepthStencil, t1->AttachDepthStencil);
swap(t0->UsePackedDepthStencil, t1->UsePackedDepthStencil);
} }