From 09c72375ab7fa614f8268f70640f9fa85c63bd60 Mon Sep 17 00:00:00 2001 From: Akash Date: Mon, 12 Dec 2016 13:30:25 +0530 Subject: [PATCH] GSDX: Pass total height of framebuffer on GetOutput() Some PSX games seem to store image data of the drawing results in an undeterminate area out of range from the current context buffer. At such cases, calculate the height of both the frame memory rectangles combined. What happens on "Crash bash" - * At first draw, scissoring is limited to SCAY0- 0 & SCAY1- 255 * At second draw, scissoring is limited to SCAY0- 255 & SCAY0-511 Previously, we limited the height to the value of one single output texture, so instead of that let's calculate the total height of both the two buffers combined to prevent such issues. --- plugins/GSdx/GSRendererCL.cpp | 2 +- plugins/GSdx/GSRendererCS.cpp | 2 +- plugins/GSdx/GSRendererHW.cpp | 2 +- plugins/GSdx/GSRendererSW.cpp | 2 +- plugins/GSdx/GSState.cpp | 14 ++++++++++++++ plugins/GSdx/GSState.h | 1 + 6 files changed, 19 insertions(+), 4 deletions(-) diff --git a/plugins/GSdx/GSRendererCL.cpp b/plugins/GSdx/GSRendererCL.cpp index 4f0dcc373e..f6615ec0f0 100644 --- a/plugins/GSdx/GSRendererCL.cpp +++ b/plugins/GSdx/GSRendererCL.cpp @@ -169,7 +169,7 @@ GSTexture* GSRendererCL::GetOutput(int i, int& y_offset) const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; int w = DISPFB.FBW * 64; - int h = GetFrameRect(i).height(); + int h = GetFramebufferHeight(); // TODO: round up bottom diff --git a/plugins/GSdx/GSRendererCS.cpp b/plugins/GSdx/GSRendererCS.cpp index d69020236b..072edab8e7 100644 --- a/plugins/GSdx/GSRendererCS.cpp +++ b/plugins/GSdx/GSRendererCS.cpp @@ -345,7 +345,7 @@ GSTexture* GSRendererCS::GetOutput(int i, int& y_offset) const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; int w = DISPFB.FBW * 64; - int h = GetFrameRect(i).height(); + int h = GetFramebufferHeight(); // TODO: round up bottom diff --git a/plugins/GSdx/GSRendererHW.cpp b/plugins/GSdx/GSRendererHW.cpp index 81940b093e..4b8e3f3097 100644 --- a/plugins/GSdx/GSRendererHW.cpp +++ b/plugins/GSdx/GSRendererHW.cpp @@ -219,7 +219,7 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset) GSTexture* t = NULL; - if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GetFrameRect(i).height())) + if(GSTextureCache::Target* rt = m_tc->LookupTarget(TEX0, m_width, m_height, GetFramebufferHeight())) { t = rt->m_texture; diff --git a/plugins/GSdx/GSRendererSW.cpp b/plugins/GSdx/GSRendererSW.cpp index 0abc38c1c0..5d0de3480f 100644 --- a/plugins/GSdx/GSRendererSW.cpp +++ b/plugins/GSdx/GSRendererSW.cpp @@ -165,7 +165,7 @@ GSTexture* GSRendererSW::GetOutput(int i, int& y_offset) const GSRegDISPFB& DISPFB = m_regs->DISP[i].DISPFB; int w = DISPFB.FBW * 64; - int h = GetFrameRect(i).height(); + int h = GetFramebufferHeight(); // TODO: round up bottom diff --git a/plugins/GSdx/GSState.cpp b/plugins/GSdx/GSState.cpp index 319cf8a8c2..fd68b0b894 100644 --- a/plugins/GSdx/GSState.cpp +++ b/plugins/GSdx/GSState.cpp @@ -473,6 +473,20 @@ GSVector4i GSState::GetFrameRect(int i) return rectangle; } +int GSState::GetFramebufferHeight() +{ + const GSVector4i output[2] = { GetFrameRect(0), GetFrameRect(1) }; + // Framebuffer height is 11 bits max according to GS user manual + const int height_limit = (1 << 11); + int max_height = std::max(output[0].height(), output[1].height()); + int frame_memory_height = std::max(max_height, output[0].runion_ordered(output[1]).height() % height_limit); + + if (frame_memory_height > 1024) + GL_PERF("Massive framebuffer height detected! (height:%d)", frame_memory_height); + + return frame_memory_height; +} + bool GSState::IsEnabled(int i) { ASSERT(i >= 0 && i < 2); diff --git a/plugins/GSdx/GSState.h b/plugins/GSdx/GSState.h index d60e684c13..b9a9fea425 100644 --- a/plugins/GSdx/GSState.h +++ b/plugins/GSdx/GSState.h @@ -242,6 +242,7 @@ public: void ResetHandlers(); + int GetFramebufferHeight(); GSVector4i GetDisplayRect(int i = -1, bool merged_rect = false); GSVector4i GetFrameRect(int i = -1); GSVideoMode GetVideoMode();