Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions nel/include/nel/3d/driver.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,9 @@ class IDriver : public NLMISC::CRefCount
/// Clear the current target surface stencil buffer. The function ignores the viewport settings but uses the scissor.
virtual bool clearStencilBuffer(sint stencilval=0) = 0;

/// Clear both the depth and stencil buffers in one call. Drivers may override for efficiency.
virtual bool clearDepthStencil(float zval=1, sint stencilval=0) { clearZBuffer(zval); clearStencilBuffer(stencilval); return true; }

/// Set the color mask filter through where the operation done will pass
virtual void setColorMask(bool bRed, bool bGreen, bool bBlue, bool bAlpha) = 0;
// @}
Expand Down
43 changes: 42 additions & 1 deletion nel/src/3d/driver/opengl3/driver_opengl3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -710,6 +710,18 @@ bool CDriverGL3::activeFrameBufferObject(ITexture * tex)
}
else
{
// Invalidate depth/stencil attachments before unbinding the FBO.
// On ANGLE (Windows/Android WebGL), switching away from an FBO without
// invalidating forces an expensive depth/stencil resolve/copy. This hint
// tells the driver the data is no longer needed, avoiding the stall.
// (STORE_OP_DONT_CARE on Vulkan, DiscardView on D3D11)
const GLenum attachments[2] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
#ifdef USE_OPENGLES3
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#else
if (_Extensions.ARBInvalidateSubdata)
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#endif
_DriverGLStates.forceBindFramebuffer(0);
return true;
}
Expand Down Expand Up @@ -753,7 +765,8 @@ bool CDriverGL3::clearZBuffer(float zval)
{
H_AUTO_OGL(CDriverGL3_clearZBuffer);

_DriverGLStates.enableZWrite(true);
// glClearBufferfv is not affected by the depth write mask (GL spec),
// so enableZWrite(true) is not needed here.
nglClearBufferfv(GL_DEPTH, 0, &zval);

return true;
Expand All @@ -769,6 +782,19 @@ bool CDriverGL3::clearStencilBuffer(sint stencilval)
return true;
}

// --------------------------------------------------
bool CDriverGL3::clearDepthStencil(float zval, sint stencilval)
{
H_AUTO_OGL(CDriverGL3_clearDepthStencil)

// Combined depth/stencil clear: one GL call instead of two.
// On ANGLE/D3D11 this maps to a single ClearDepthStencilView with
// D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, avoiding two separate calls.
nglClearBufferfi(GL_DEPTH_STENCIL, 0, zval, stencilval);

return true;
}

// --------------------------------------------------
void CDriverGL3::setColorMask (bool bRed, bool bGreen, bool bBlue, bool bAlpha)
{
Expand Down Expand Up @@ -838,6 +864,21 @@ bool CDriverGL3::swapBuffers()
_SwapBufferSync[syncI] = nglFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
nlassert(_SwapBufferSync[syncI]);

// Invalidate the default framebuffer's depth/stencil before the swap.
// The depth/stencil data is never needed across frames. Without this hint,
// ANGLE stores the depth/stencil during present (an expensive resolve/copy
// on D3D11, and STORE_OP_STORE on Vulkan). With invalidation, ANGLE can
// skip the store (DiscardView on D3D11, STORE_OP_DONT_CARE on Vulkan).
{
const GLenum attachments[2] = { GL_DEPTH, GL_STENCIL };
#ifdef USE_OPENGLES3
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#else
if (_Extensions.ARBInvalidateSubdata)
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#endif
}

++_SwapBufferCounter;

if (!_WndActive)
Expand Down
1 change: 1 addition & 0 deletions nel/src/3d/driver/opengl3/driver_opengl3.h
Original file line number Diff line number Diff line change
Expand Up @@ -542,6 +542,7 @@ class CDriverGL3 : public IDriver

virtual bool clearZBuffer(float zval=1);
virtual bool clearStencilBuffer(sint stencilval=0);
virtual bool clearDepthStencil(float zval=1, sint stencilval=0);
virtual void setColorMask (bool bRed, bool bGreen, bool bBlue, bool bAlpha);
virtual void setDepthRange(float znear, float zfar);
virtual void getDepthRange(float &znear, float &zfar) const;
Expand Down
15 changes: 15 additions & 0 deletions nel/src/3d/driver/opengl3/driver_opengl3_extension.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,7 @@ PFNGLGENERATEMIPMAPPROC nglGenerateMipmap;
PFNGLBLITFRAMEBUFFERPROC nglBlitFramebuffer;
PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC nglRenderbufferStorageMultisample;
PFNGLFRAMEBUFFERTEXTURELAYERPROC nglFramebufferTextureLayer;
PFNGLINVALIDATEFRAMEBUFFERPROC nglInvalidateFramebuffer;

PFNGLACTIVETEXTUREPROC nglActiveTexture;

Expand Down Expand Up @@ -503,6 +504,9 @@ static bool setupGLCore(std::vector<const char *> &glext)
CHECK_ADDRESS(PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC, glRenderbufferStorageMultisample);
CHECK_ADDRESS(PFNGLFRAMEBUFFERTEXTURELAYERPROC, glFramebufferTextureLayer);

// GL 4.3 / ARB_invalidate_subdata: optional on GL 3.3, always available on GLES 3.0
nglInvalidateFramebuffer = (PFNGLINVALIDATEFRAMEBUFFERPROC)nglGetProcAddress("glInvalidateFramebuffer");

CHECK_ADDRESS(PFNGLACTIVETEXTUREPROC, glActiveTexture);

CHECK_ADDRESS(PFNGLCOMPRESSEDTEXIMAGE3DPROC, glCompressedTexImage3D);
Expand Down Expand Up @@ -603,6 +607,14 @@ static bool setupAMDPinnedMemory(std::vector<const char *> &glext)
return true;
}

// *********************************
static bool setupARBInvalidateSubdata(std::vector<const char *> &glext)
{
CHECK_EXT_2("GL_ARB_invalidate_subdata");

return true;
}

// *********************************
static bool setupNVXGPUMemoryInfo(std::vector<const char *> &glext)
{
Expand Down Expand Up @@ -701,6 +713,9 @@ bool registerGlExtensions(CGlExtensions &ext)
// Check GL_AMD_pinned_memory
ext.AMDPinnedMemory = false; // setupAMDPinnedMemory(glext); // TODO: Proper frame sync check

// Check GL_ARB_invalidate_subdata (GL 4.3 core; optional on GL 3.3)
ext.ARBInvalidateSubdata = setupARBInvalidateSubdata(glext);

// Memory info extensions
ext.NVXGPUMemoryInfo = setupNVXGPUMemoryInfo(glext);
ext.ATIMeminfo = setupATIMeminfo(glext);
Expand Down
5 changes: 5 additions & 0 deletions nel/src/3d/driver/opengl3/driver_opengl3_extension.h
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ struct CGlExtensions
bool EXTTextureCompressionS3TC;
bool EXTTextureFilterAnisotropic;
float EXTTextureFilterAnisotropicMaximum;
bool ARBInvalidateSubdata;
bool AMDPinnedMemory;

// Extensions to get memory info
Expand Down Expand Up @@ -95,6 +96,7 @@ struct CGlExtensions
EXTTextureCompressionS3TC = false;
EXTTextureFilterAnisotropic = false;
EXTTextureFilterAnisotropicMaximum = 0.f;
ARBInvalidateSubdata = false;
AMDPinnedMemory = false;

NVXGPUMemoryInfo = false;
Expand Down Expand Up @@ -133,6 +135,7 @@ struct CGlExtensions

result += "\n Buffers: ";
result += AMDPinnedMemory ? "AMDPinnedMemory " : "";
result += ARBInvalidateSubdata ? "ARBInvalidateSubdata " : "";

result += "\n Memory info: ";
result += NVXGPUMemoryInfo ? "NVXGPUMemoryInfo " : "";
Expand Down Expand Up @@ -284,6 +287,7 @@ namespace NLDRIVERGL3 {
#define nglBlitFramebuffer glBlitFramebuffer
#define nglRenderbufferStorageMultisample glRenderbufferStorageMultisample
#define nglFramebufferTextureLayer glFramebufferTextureLayer
#define nglInvalidateFramebuffer glInvalidateFramebuffer

#define nglActiveTexture glActiveTexture

Expand Down Expand Up @@ -491,6 +495,7 @@ extern PFNGLGENERATEMIPMAPPROC nglGenerateMipmap;
extern PFNGLBLITFRAMEBUFFERPROC nglBlitFramebuffer;
extern PFNGLRENDERBUFFERSTORAGEMULTISAMPLEPROC nglRenderbufferStorageMultisample;
extern PFNGLFRAMEBUFFERTEXTURELAYERPROC nglFramebufferTextureLayer;
extern PFNGLINVALIDATEFRAMEBUFFERPROC nglInvalidateFramebuffer;

extern PFNGLACTIVETEXTUREPROC nglActiveTexture;

Expand Down
25 changes: 24 additions & 1 deletion nel/src/3d/driver/opengl3/driver_opengl3_texture.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -248,12 +248,32 @@ bool CTextureDrvInfosGL3::activeFrameBufferObject(ITexture * tex)
{
_Driver->_DriverGLStates.forceBindTexture(TextureMode, 0);
_Driver->_DriverGLStates.forceBindFramebuffer(FBOId);
// Do NOT invalidate depth/stencil here at bind time.
// The application clears depth/stencil immediately after binding,
// which allows ANGLE to use LOAD_OP_CLEAR for the render pass.
// An invalidation here would downgrade that to LOAD_OP_DONT_CARE
// followed by a mid-pass vkCmdClearAttachments, which is slower.
}
else
return false;
}
else
{
// Invalidate depth/stencil attachments before unbinding the FBO.
// On ANGLE (Windows/Android WebGL), switching away from an FBO without
// invalidating forces an expensive depth/stencil resolve/copy. This hint
// tells the driver the data is no longer needed, avoiding the stall.
// (STORE_OP_DONT_CARE on Vulkan, DiscardView on D3D11)
if (AttachDepthStencil)
{
const GLenum attachments[2] = { GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT };
#ifdef USE_OPENGLES3
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#else
if (_Driver->_Extensions.ARBInvalidateSubdata)
nglInvalidateFramebuffer(GL_FRAMEBUFFER, 2, attachments);
#endif
}
_Driver->_DriverGLStates.forceBindFramebuffer(0);
}

Expand Down Expand Up @@ -1765,7 +1785,10 @@ bool CDriverGL3::setRenderTarget (ITexture *tex, uint32 x, uint32 y, uint32 widt
}
else if (_RenderTargetFBO)
{
activeFrameBufferObject(NULL);
// Deactivate through the texture-level method so it can use per-FBO
// state (e.g. AttachDepthStencil) for conditional invalidation.
CTextureDrvInfosGL3* gltext = (CTextureDrvInfosGL3*)(ITextureDrvInfos*)(_RenderTargetFBO->TextureDrvShare->DrvTexture);
gltext->activeFrameBufferObject(NULL);
setupViewport(_OldViewport);
_OldViewport = _CurrViewport;

Expand Down
3 changes: 1 addition & 2 deletions nel/src/3d/driver_user.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1357,8 +1357,7 @@ void CDriverUser::clearBuffers(CRGBA col)
NL3D_HAUTO_CLEAR_DRIVER;

_Driver->clear2D(col);
_Driver->clearZBuffer();
_Driver->clearStencilBuffer();
_Driver->clearDepthStencil();
}
// ***************************************************************************
void CDriverUser::swapBuffers()
Expand Down
Loading