From 866173a481d2387f01c9a13bad98c5e2c1f92baf Mon Sep 17 00:00:00 2001 From: Gregory Hainaut Date: Thu, 11 Aug 2016 21:14:58 +0200 Subject: [PATCH] gsdx ogl: move zbuffer emulation code into a dedicated function * Code was factorized a bit with the help of max_z * Add an extra optimization if test is ZTST_GEQUAL and min z value is the biggest value. Z test will always be pass. Note: due to float rounding (23 bits mantissa vs 24 bits depth) the test is done against 0xFF_FFFE and not 0xFF_FFFF. It is wrong but GPU will also use float so impact will be null. --- plugins/GSdx/GSRendererOGL.cpp | 93 +++++++++++++++++----------------- plugins/GSdx/GSRendererOGL.h | 1 + 2 files changed, 48 insertions(+), 46 deletions(-) diff --git a/plugins/GSdx/GSRendererOGL.cpp b/plugins/GSdx/GSRendererOGL.cpp index cd08ab519b..ba5f96267f 100644 --- a/plugins/GSdx/GSRendererOGL.cpp +++ b/plugins/GSdx/GSRendererOGL.cpp @@ -215,6 +215,52 @@ void GSRendererOGL::EmulateAtst(const int pass, const GSTextureCache::Source* te } } +void GSRendererOGL::EmulateZbuffer() +{ + if (m_context->TEST.ZTE) { + m_om_dssel.ztst = m_context->TEST.ZTST; + m_om_dssel.zwe = !m_context->ZBUF.ZMSK; + } else { + m_om_dssel.ztst = ZTST_ALWAYS; + } + + uint32 max_z; + uint32 max_z_flt; + if (m_context->ZBUF.PSM == PSM_PSMZ32) { + max_z = 0xFFFFFFFF; + max_z_flt = 0xFFFFFFFF; + } else if (m_context->ZBUF.PSM == PSM_PSMZ24) { + // Float mantissa is only 23 bits so the max 24 bits was rounded down + max_z = 0xFFFFFF; + max_z_flt = 0xFFFFFE; + } else { + max_z = 0xFFFF; + max_z_flt = 0xFFFF; + } + + // The real GS appears to do no masking based on the Z buffer format and writing larger Z values + // than the buffer supports seems to be an error condition on the real GS, causing it to crash. + // We are probably receiving bad coordinates from VU1 in these cases. + vs_cb.DepthMask = GSVector2i(max_z, max_z); + + if (m_om_dssel.ztst >= ZTST_ALWAYS && m_om_dssel.zwe && (m_context->ZBUF.PSM != PSM_PSMZ32)) { + if (m_vt.m_max.p.z > max_z) { + ASSERT(m_vt.m_min.p.z > max_z); // sfex capcom logo + // Fixme :Following conditional fixes some dialog frame in Wild Arms 3, but may not be what was intended. + if (m_vt.m_min.p.z > max_z) { + GL_INS("Bad Z size on %s buffers", psm_str(m_context->ZBUF.PSM)); + m_om_dssel.ztst = ZTST_ALWAYS; + } + } + } + + // Minor optimization of a corner case (it allow to better emulate some alpha test effects) + if (m_om_dssel.ztst == ZTST_GEQUAL && m_vt.m_min.p.z >= max_z_flt) { + GL_INS("Optimize Z test GEQUAL to ALWAYS (%s)", psm_str(m_context->ZBUF.PSM)); + m_om_dssel.ztst = ZTST_ALWAYS; + } +} + void GSRendererOGL::EmulateTextureShuffleAndFbmask() { if (m_texture_shuffle) { @@ -1180,55 +1226,10 @@ void GSRendererOGL::DrawPrims(GSTexture* rt, GSTexture* ds, GSTextureCache::Sour // om - if (m_context->TEST.ZTE) - { - m_om_dssel.ztst = m_context->TEST.ZTST; - m_om_dssel.zwe = !m_context->ZBUF.ZMSK; - } - else - { - m_om_dssel.ztst = ZTST_ALWAYS; - } + EmulateZbuffer(); // will update VS depth mask // vs - // The real GS appears to do no masking based on the Z buffer format and writing larger Z values - // than the buffer supports seems to be an error condition on the real GS, causing it to crash. - // We are probably receiving bad coordinates from VU1 in these cases. - vs_cb.DepthMask = GSVector2i(0xFFFFFFFF, 0xFFFFFFFF); - - if (m_om_dssel.ztst >= ZTST_ALWAYS && m_om_dssel.zwe) - { - if (m_context->ZBUF.PSM == PSM_PSMZ24) - { - if (m_vt.m_max.p.z > 0xffffff) - { - ASSERT(m_vt.m_min.p.z > 0xffffff); - // Fixme :Following conditional fixes some dialog frame in Wild Arms 3, but may not be what was intended. - if (m_vt.m_min.p.z > 0xffffff) - { - GL_INS("Bad Z size on 24 bits buffers") - vs_cb.DepthMask = GSVector2i(0x00FFFFFF, 0x00FFFFFF); - m_om_dssel.ztst = ZTST_ALWAYS; - } - } - } - else if (m_context->ZBUF.PSM == PSM_PSMZ16 || m_context->ZBUF.PSM == PSM_PSMZ16S) - { - if (m_vt.m_max.p.z > 0xffff) - { - ASSERT(m_vt.m_min.p.z > 0xffff); // sfex capcom logo - // Fixme : Same as above, I guess. - if (m_vt.m_min.p.z > 0xffff) - { - GL_INS("Bad Z size on 16 bits buffers") - vs_cb.DepthMask = GSVector2i(0x0000FFFF, 0x0000FFFF); - m_om_dssel.ztst = ZTST_ALWAYS; - } - } - } - } - // FIXME Opengl support half pixel center (as dx10). Code could be easier!!! float sx = 2.0f * rtscale.x / (rtsize.x << 4); float sy = 2.0f * rtscale.y / (rtsize.y << 4); diff --git a/plugins/GSdx/GSRendererOGL.h b/plugins/GSdx/GSRendererOGL.h index fc524d4d34..84f0f730ed 100644 --- a/plugins/GSdx/GSRendererOGL.h +++ b/plugins/GSdx/GSRendererOGL.h @@ -80,6 +80,7 @@ class GSRendererOGL final : public GSRendererHW inline void EmulateBlending(bool DATE_GL42); inline void EmulateTextureSampler(const GSTextureCache::Source* tex); inline void EmulateAtst(const int pass, const GSTextureCache::Source* tex); + inline void EmulateZbuffer(); public: GSRendererOGL();