GSdx-HW: Move scaling code to separate subroutine

Move the custom resolution scaling code to a separate subroutine and
allow future RT buffer resize calls when the buffer size isn't enough.

(Example: when a game's CRTC/Framebuffer size changes. The older code
didn't consider such cases)
This commit is contained in:
Akash 2017-05-19 23:27:17 +05:30 committed by Gregory Hainaut
parent a04d9fa388
commit 23fa0657a7
2 changed files with 54 additions and 46 deletions

View File

@ -65,6 +65,12 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc)
void GSRendererHW::SetScaling() void GSRendererHW::SetScaling()
{ {
if (!m_upscale_multiplier)
{
CustomResolutionScaling();
return;
}
GSVector2i crtc_size(GetDisplayRect().width(), GetDisplayRect().height()); GSVector2i crtc_size(GetDisplayRect().width(), GetDisplayRect().height());
// Details of (potential) perf impact of a big framebuffer // Details of (potential) perf impact of a big framebuffer
@ -111,52 +117,6 @@ void GSRendererHW::SetScaling()
int upscaled_fb_w = fb_width * m_upscale_multiplier; int upscaled_fb_w = fb_width * m_upscale_multiplier;
int upscaled_fb_h = fb_height * m_upscale_multiplier; int upscaled_fb_h = fb_height * m_upscale_multiplier;
bool good_rt_size = m_width >= upscaled_fb_w && m_height >= upscaled_fb_h; bool good_rt_size = m_width >= upscaled_fb_w && m_height >= upscaled_fb_h;
bool initialized_register_state = (m_context->FRAME.FBW > 1) && (crtc_size.y > 1);
if (!m_upscale_multiplier && initialized_register_state)
{
if (m_height == m_custom_height)
{
const float scaling_ratio = ceil(static_cast<float>(m_custom_height) / crtc_size.y);
// Avoid using a scissor value which is too high, developers can even leave the scissor to max (2047)
// at some cases when they don't want to limit the rendering size. Our assumption is that developers
// set the scissor to the actual data in the buffer. Let's use the scissoring value only at such cases
const int scissor_height = std::min(640u, (m_context->SCISSOR.SCAY1 - m_context->SCISSOR.SCAY0) + 1);
const int single_buffer_size = std::max(GetDisplayRect().height(), scissor_height);
// We have two contexts of framebuffer height -
// One for lower memory consumption and low accuracy
// Another one for higher memory consumption at necessary scenarios for higher accuracy
std::array<int, 2> framebuffer_height;
// When Large Framebuffer is disabled - Let's only consider the height of the display rectangle
// as the base (This is wrong implementation when we consider it theoretically as CRTC has no relation
// to the Framebuffer size)
framebuffer_height[0] = static_cast<int>(round((crtc_size.y * scaling_ratio)));
// When Large Framebuffer is enabled - We also consider for potential scissor sizes which are around
// the size of the actual image data stored. (Helps ICO to properly scale to right size by help of the
// scissoring values) Display rectangle has a height of 256 but scissor has a height of 512 which seems to
// be the real buffer size.
framebuffer_height[1] = static_cast<int>(round(single_buffer_size * scaling_ratio));
m_tc->RemovePartial();
m_width = std::max(m_width, native_buffer.x);
m_height = std::max(framebuffer_height[m_large_framebuffer], native_buffer.y);
std::string overhead = to_string(framebuffer_height[1] - framebuffer_height[0]);
std::string message = "(Custom resolution) Framebuffer size set to " + to_string(crtc_size.x) + "x" + to_string(crtc_size.y);
message += " (" + to_string(m_width) + "x" + to_string(m_height) + ")\n";
if (m_large_framebuffer)
{
message += "Additional " + overhead + " pixels overhead by enabling Large Framebuffer\n";
}
else
{
message += "Saved " + overhead + " pixels overhead by disabling Large Framebuffer\n";
}
printf("%s", message);
}
}
// No need to resize for native/custom resolutions as default size will be enough for native and we manually get RT Buffer size for custom. // No need to resize for native/custom resolutions as default size will be enough for native and we manually get RT Buffer size for custom.
// don't resize until the display rectangle and register states are stabilized. // don't resize until the display rectangle and register states are stabilized.
@ -169,6 +129,53 @@ void GSRendererHW::SetScaling()
printf("Frame buffer size set to %dx%d (%dx%d)\n", fb_width, fb_height , m_width, m_height); printf("Frame buffer size set to %dx%d (%dx%d)\n", fb_width, fb_height , m_width, m_height);
} }
void GSRendererHW::CustomResolutionScaling()
{
const int crtc_width = GetDisplayRect().width();
const int crtc_height = GetDisplayRect().height();
const float scaling_ratio = std::ceil(static_cast<float>(m_custom_height) / crtc_height);
// Avoid using a scissor value which is too high, developers can even leave the scissor to max (2047)
// at some cases when they don't want to limit the rendering size. Our assumption is that developers
// set the scissor to the actual data in the buffer. Let's use the scissoring value only at such cases
const int scissor_height = std::min(640, static_cast<int>(m_context->SCISSOR.SCAY1 - m_context->SCISSOR.SCAY0) + 1);
const int single_buffer_size = std::max(GetDisplayRect().height(), scissor_height);
// We have two contexts of framebuffer height -
// One for lower memory consumption and low accuracy
// Another one for higher memory consumption at necessary scenarios for higher accuracy
std::array<int, 2> framebuffer_height;
// When Large Framebuffer is disabled - Let's only consider the height of the display rectangle
// as the base (This is wrong implementation when we consider it theoretically as CRTC has no relation
// to the Framebuffer size)
framebuffer_height[0] = static_cast<int>(std::round((crtc_height * scaling_ratio)));
// When Large Framebuffer is enabled - We also consider for potential scissor sizes which are around
// the size of the actual image data stored. (Helps ICO to properly scale to right size by help of the
// scissoring values) Display rectangle has a height of 256 but scissor has a height of 512 which seems to
// be the real buffer size.
framebuffer_height[1] = static_cast<int>(std::round(single_buffer_size * scaling_ratio));
if (m_width >= m_custom_width && m_height >= framebuffer_height[m_large_framebuffer])
return;
m_tc->RemovePartial();
m_width = std::max(m_width, native_buffer.x);
m_height = std::max(framebuffer_height[m_large_framebuffer], native_buffer.y);
std::string overhead = std::to_string(framebuffer_height[1] - framebuffer_height[0]);
std::string message = "(Custom resolution) Framebuffer size set to " + std::to_string(crtc_width) + "x" + std::to_string(crtc_height);
message += " (" + std::to_string(m_width) + "x" + std::to_string(m_height) + ")\n";
if (m_large_framebuffer)
{
message += "Additional " + overhead + " pixels overhead by enabling Large Framebuffer\n";
}
else
{
message += "Saved " + overhead + " pixels overhead by disabling Large Framebuffer\n";
}
printf("%s", message.c_str());
}
GSRendererHW::~GSRendererHW() GSRendererHW::~GSRendererHW()
{ {
delete m_tc; delete m_tc;

View File

@ -156,6 +156,7 @@ protected:
GSVector2i m_lod; // Min & Max level of detail GSVector2i m_lod; // Min & Max level of detail
const GSVector2i native_buffer = GSVector2i(1280, 1024); const GSVector2i native_buffer = GSVector2i(1280, 1024);
void CustomResolutionScaling();
public: public:
GSRendererHW(GSTextureCache* tc); GSRendererHW(GSTextureCache* tc);