From 32172d30af5cd67c17a35e77214386cb772543be Mon Sep 17 00:00:00 2001 From: Sergey Lipskiy Date: Sun, 11 Sep 2016 18:08:03 +0700 Subject: [PATCH] Fix depth buffer clear for aux buffers. --- src/DepthBuffer.cpp | 13 ++++++++----- src/DepthBuffer.h | 4 ++-- src/FrameBuffer.cpp | 12 ++++++++++-- src/OpenGL.cpp | 4 ++-- src/OpenGL.h | 2 +- src/gDP.cpp | 14 ++++++++------ 6 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/DepthBuffer.cpp b/src/DepthBuffer.cpp index db3f2fd6..2053001c 100644 --- a/src/DepthBuffer.cpp +++ b/src/DepthBuffer.cpp @@ -17,7 +17,7 @@ const GLuint ZlutImageUnit = 0; const GLuint TlutImageUnit = 1; const GLuint depthImageUnit = 2; -DepthBuffer::DepthBuffer() : m_address(0), m_width(0), m_uly(0), m_lry(0), +DepthBuffer::DepthBuffer() : m_address(0), m_width(0), m_ulx(0), m_uly(0), m_lrx(0), m_lry(0), m_depthImageFBO(0), m_pDepthImageTexture(nullptr), m_pDepthBufferTexture(nullptr), m_depthRenderbuffer(0), m_depthRenderbufferWidth(0), m_cleared(false), m_pResolveDepthBufferTexture(nullptr), m_resolved(false), @@ -29,7 +29,8 @@ DepthBuffer::DepthBuffer() : m_address(0), m_width(0), m_uly(0), m_lry(0), } DepthBuffer::DepthBuffer(DepthBuffer && _other) : - m_address(_other.m_address), m_width(_other.m_width), m_uly(_other.m_uly), m_lry(_other.m_lry), + m_address(_other.m_address), m_width(_other.m_width), + m_ulx(_other.m_ulx), m_uly(_other.m_uly), m_lrx(_other.m_lrx), m_lry(_other.m_lry), m_depthImageFBO(_other.m_depthImageFBO), m_pDepthImageTexture(_other.m_pDepthImageTexture), m_pDepthBufferTexture(_other.m_pDepthBufferTexture), m_depthRenderbuffer(_other.m_depthRenderbuffer), m_depthRenderbufferWidth(_other.m_depthRenderbufferWidth), m_cleared(_other.m_cleared), m_pResolveDepthBufferTexture(_other.m_pResolveDepthBufferTexture), m_resolved(_other.m_resolved), @@ -102,7 +103,7 @@ void DepthBuffer::initDepthImageTexture(FrameBuffer * _pBuffer) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0); glBindFramebuffer(GL_DRAW_FRAMEBUFFER, _pBuffer->m_FBO); - depthBufferList().clearBuffer(0, VI.height); + depthBufferList().clearBuffer(0, 0, VI.width, VI.height); #endif // GL_IMAGE_TEXTURES_SUPPORT } @@ -409,12 +410,14 @@ void DepthBufferList::saveBuffer(u32 _address) } -void DepthBufferList::clearBuffer(u32 _uly, u32 _lry) +void DepthBufferList::clearBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry) { if (m_pCurrent == nullptr) return; m_pCurrent->m_cleared = true; + m_pCurrent->m_ulx = _ulx; m_pCurrent->m_uly = _uly; + m_pCurrent->m_lrx = _lrx; m_pCurrent->m_lry = _lry; #ifdef GL_IMAGE_TEXTURES_SUPPORT if (m_pCurrent->m_depthImageFBO == 0 || !video().getRender().isImageTexturesSupported() || config.frameBufferEmulation.N64DepthCompare == 0) @@ -424,7 +427,7 @@ void DepthBufferList::clearBuffer(u32 _uly, u32 _lry) glBindFramebuffer(GL_DRAW_FRAMEBUFFER, m_pCurrent->m_depthImageFBO); const u32 cycleType = gDP.otherMode.cycleType; gDP.otherMode.cycleType = G_CYC_FILL; - video().getRender().drawRect(0,0,VI.width, VI.height, color); + video().getRender().drawRect(_ulx, _uly, _lrx, _lry, color); gDP.otherMode.cycleType = cycleType; glBindImageTexture(depthImageUnit, m_pCurrent->m_pDepthImageTexture->glName, 0, GL_FALSE, 0, GL_READ_WRITE, fboFormats.depthImageInternalFormat); frameBufferList().setCurrentDrawBuffer(); diff --git a/src/DepthBuffer.h b/src/DepthBuffer.h index cfef1abb..97ec1f1e 100644 --- a/src/DepthBuffer.h +++ b/src/DepthBuffer.h @@ -21,7 +21,7 @@ struct DepthBuffer void bindDepthImageTexture(); u32 m_address, m_width; - u32 m_uly, m_lry; // Top and bottom bounds of fillrect command. + u32 m_ulx, m_uly, m_lrx, m_lry; // Parameters of fillrect command. GLuint m_depthImageFBO; CachedTexture *m_pDepthImageTexture; CachedTexture *m_pDepthBufferTexture; @@ -49,7 +49,7 @@ public: void destroy(); void saveBuffer(u32 _address); void removeBuffer(u32 _address); - void clearBuffer(u32 _uly, u32 _lry); + void clearBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry); void setNotCleared(); DepthBuffer *findBuffer(u32 _address); DepthBuffer * getCurrent() const {return m_pCurrent;} diff --git a/src/FrameBuffer.cpp b/src/FrameBuffer.cpp index 3fd4398f..640c3fef 100644 --- a/src/FrameBuffer.cpp +++ b/src/FrameBuffer.cpp @@ -553,7 +553,11 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt } OGLVideo & ogl = video(); + bool bPrevIsDepth = false; + if (m_pCurrent != nullptr) { + bPrevIsDepth = m_pCurrent->m_isDepthBuffer; + // Correct buffer's end address if (!m_pCurrent->isAuxiliary()) { if (gDP.colorImage.height > 200) @@ -639,8 +643,12 @@ void FrameBufferList::saveBuffer(u32 _address, u16 _format, u16 _size, u16 _widt ); #endif - if (m_pCurrent->isAuxiliary()) - ogl.getRender().clearDepthBuffer(0, 0); + if (m_pCurrent->isAuxiliary() && m_pCurrent->m_pDepthBuffer != nullptr && bPrevIsDepth) { + // N64 games may use partial depth buffer clear for aux buffers + // It will not work for GL, so we have to force clear depth buffer for aux buffer + const DepthBuffer * pDepth = m_pCurrent->m_pDepthBuffer; + ogl.getRender().clearDepthBuffer(pDepth->m_ulx, pDepth->m_uly, pDepth->m_lrx, pDepth->m_lry); + } m_pCurrent->m_isDepthBuffer = _address == gDP.depthImageAddress; m_pCurrent->m_isPauseScreen = m_pCurrent->m_isOBScreen = false; diff --git a/src/OpenGL.cpp b/src/OpenGL.cpp index c933bb19..dbba25cd 100644 --- a/src/OpenGL.cpp +++ b/src/OpenGL.cpp @@ -1853,12 +1853,12 @@ void OGLRender::drawText(const char *_pText, float x, float y) TextDrawer::get().renderText(_pText, x, y); } -void OGLRender::clearDepthBuffer(u32 _uly, u32 _lry) +void OGLRender::clearDepthBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry) { if (!_canDraw()) return; - depthBufferList().clearBuffer(_uly, _lry); + depthBufferList().clearBuffer(_ulx, _uly, _lrx, _lry); glDisable( GL_SCISSOR_TEST ); diff --git a/src/OpenGL.h b/src/OpenGL.h index bdf7fd2f..9ddd445e 100644 --- a/src/OpenGL.h +++ b/src/OpenGL.h @@ -135,7 +135,7 @@ public: GLint _dstX0, GLint _dstY0, GLint _dstX1, GLint _dstY1, GLuint _dstWidth, GLuint _dstHeight, GLenum _filter); void drawText(const char *_pText, float x, float y); - void clearDepthBuffer(u32 _uly, u32 _lry); + void clearDepthBuffer(u32 _ulx, u32 _uly, u32 _lrx, u32 _lry); void clearColorBuffer( float * _pColor ); int getTrianglesCount() const {return triangles.num;} diff --git a/src/gDP.cpp b/src/gDP.cpp index 406b88e0..a9286142 100644 --- a/src/gDP.cpp +++ b/src/gDP.cpp @@ -770,21 +770,23 @@ void gDPFillRectangle( s32 ulx, s32 uly, s32 lrx, s32 lry ) // Game may use depth texture as auxilary color texture. Example: Mario Tennis // If color is not depth clear color, that is most likely the case if (gDP.fillColor.color == DepthClearColor) { + gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color); if (config.generalEmulation.enableFragmentDepthWrite == 0 || (ulx == 0 && uly == 0 && lrx == gDP.scissor.lrx && lry == gDP.scissor.lry)) { - gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color); - render.clearDepthBuffer(uly, lry); + render.clearDepthBuffer(ulx, uly, lrx, lry); bBufferCleared = true; - } + } else + depthBufferList().clearBuffer(ulx, uly, lrx, lry); } } else if (gDP.fillColor.color == DepthClearColor && gDP.otherMode.cycleType == G_CYC_FILL) { depthBufferList().saveBuffer(gDP.colorImage.address); + gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color); if (config.generalEmulation.enableFragmentDepthWrite == 0 || (ulx == 0 && uly == 0 && lrx == gDP.scissor.lrx && lry == gDP.scissor.lry)) { - gDPFillRDRAM(gDP.colorImage.address, ulx, uly, lrx, lry, gDP.colorImage.width, gDP.colorImage.size, gDP.fillColor.color); - render.clearDepthBuffer(uly, lry); + render.clearDepthBuffer(ulx, uly, lrx, lry); bBufferCleared = true; - } + } else + depthBufferList().clearBuffer(ulx, uly, lrx, lry); } if (!bBufferCleared) {