mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Correct some scaling behaviour
This commit is contained in:
parent
1d46ec2059
commit
2fc6357ac4
|
@ -2674,7 +2674,7 @@ void GSRendererHW::Draw()
|
||||||
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
||||||
IsPossibleChannelShuffle());
|
IsPossibleChannelShuffle());
|
||||||
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true,
|
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, target_scale, GSTextureCache::RenderTarget, true,
|
||||||
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect, possible_shuffle, is_possible_mem_clear && FRAME_TEX0.TBP0 != m_cached_ctx.ZBUF.Block());
|
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect, possible_shuffle, is_possible_mem_clear && FRAME_TEX0.TBP0 != m_cached_ctx.ZBUF.Block(), scale_draw < 0);
|
||||||
|
|
||||||
// Draw skipped because it was a clear and there was no target.
|
// Draw skipped because it was a clear and there was no target.
|
||||||
if (!rt)
|
if (!rt)
|
||||||
|
@ -2696,7 +2696,7 @@ void GSRendererHW::Draw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::RenderTarget, true,
|
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), (scale_draw < 0) ? src->m_from_target->GetScale() : target_scale, GSTextureCache::RenderTarget, true,
|
||||||
fm, false, force_preload, preserve_rt_color, m_r, src);
|
fm, false, force_preload, preserve_rt_color, m_r, src);
|
||||||
if (!rt) [[unlikely]]
|
if (!rt) [[unlikely]]
|
||||||
{
|
{
|
||||||
|
@ -2705,18 +2705,16 @@ void GSRendererHW::Draw()
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
if (src && src->m_from_target && src->m_target_direct && src->m_from_target == rt)
|
|
||||||
{
|
|
||||||
src->m_texture = rt->m_texture;
|
|
||||||
src->m_scale = rt->m_scale;
|
|
||||||
src->m_unscaled_size = rt->m_unscaled_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
target_scale = rt->GetScale();
|
if (src && src->m_from_target && src->m_target_direct && src->m_from_target == rt)
|
||||||
|
{
|
||||||
|
src->m_texture = rt->m_texture;
|
||||||
|
src->m_scale = rt->GetScale();
|
||||||
|
src->m_unscaled_size = rt->m_unscaled_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
target_scale = rt->GetScale();
|
||||||
|
|
||||||
// The target might have previously been a C32 format with valid alpha. If we're switching to C24, we need to preserve it.
|
// The target might have previously been a C32 format with valid alpha. If we're switching to C24, we need to preserve it.
|
||||||
preserve_rt_alpha |= (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp == 24 && rt->HasValidAlpha());
|
preserve_rt_alpha |= (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp == 24 && rt->HasValidAlpha());
|
||||||
preserve_rt_color = preserve_rt_rgb || preserve_rt_alpha;
|
preserve_rt_color = preserve_rt_rgb || preserve_rt_alpha;
|
||||||
|
@ -4760,6 +4758,10 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
|
||||||
float scale = tex->GetScale();
|
float scale = tex->GetScale();
|
||||||
HandleTextureHazards(rt, ds, tex, tmm, source_region, target_region, unscaled_size, scale, src_copy);
|
HandleTextureHazards(rt, ds, tex, tmm, source_region, target_region, unscaled_size, scale, src_copy);
|
||||||
|
|
||||||
|
// This is used for reading depth sources, so we should go off the source scale.
|
||||||
|
float scale_factor = scale;
|
||||||
|
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f);
|
||||||
|
|
||||||
if ((m_conf.ps.tex_is_fb && rt->m_rt_alpha_scale) || (tex->m_target && tex->m_from_target && tex->m_target_direct && tex->m_from_target->m_rt_alpha_scale))
|
if ((m_conf.ps.tex_is_fb && rt->m_rt_alpha_scale) || (tex->m_target && tex->m_from_target && tex->m_target_direct && tex->m_from_target->m_rt_alpha_scale))
|
||||||
m_conf.ps.rta_source_correction = 1;
|
m_conf.ps.rta_source_correction = 1;
|
||||||
|
|
||||||
|
@ -5437,9 +5439,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||||
|
|
||||||
ResetStates();
|
ResetStates();
|
||||||
|
|
||||||
const float scale_factor = rt ? rt->GetScale() : ds->GetScale();
|
|
||||||
m_conf.cb_vs.texture_offset = {};
|
m_conf.cb_vs.texture_offset = {};
|
||||||
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f);
|
|
||||||
m_conf.ps.scanmsk = env.SCANMSK.MSK;
|
m_conf.ps.scanmsk = env.SCANMSK.MSK;
|
||||||
m_conf.rt = rt ? rt->m_texture : nullptr;
|
m_conf.rt = rt ? rt->m_texture : nullptr;
|
||||||
m_conf.ds = ds ? ds->m_texture : nullptr;
|
m_conf.ds = ds ? ds->m_texture : nullptr;
|
||||||
|
@ -6058,6 +6058,9 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
const float scale_factor = rt ? rt->GetScale() : ds->GetScale();
|
||||||
|
m_conf.cb_ps.ScaleFactor = GSVector4(scale_factor * (1.0f / 16.0f), 1.0f / scale_factor, scale_factor, 0.0f);
|
||||||
|
|
||||||
m_conf.ps.tfx = 4;
|
m_conf.ps.tfx = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7206,28 +7209,28 @@ bool GSRendererHW::TextureCoversWithoutGapsNotEqual()
|
||||||
|
|
||||||
int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
|
int GSRendererHW::IsScalingDraw(GSTextureCache::Source* src, bool no_gaps)
|
||||||
{
|
{
|
||||||
// Try to detect if a game is downscaling/upscaling the image in order to do post processing/bloom effects.
|
|
||||||
const GSVector2i draw_size = GSVector2i(m_vt.m_max.p.x - m_vt.m_min.p.x, m_vt.m_max.p.y - m_vt.m_min.p.y);
|
|
||||||
const GSVector2i tex_size = GSVector2i(m_vt.m_max.t.x - m_vt.m_min.t.x, m_vt.m_max.t.y - m_vt.m_min.t.y);
|
|
||||||
const bool is_downscale = (tex_size.x / 2.0f) >= draw_size.x && (tex_size.y / 2.0f) >= draw_size.y;
|
|
||||||
if (is_downscale && draw_size.x >= PCRTCDisplays.GetResolution().x)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (GSConfig.UserHacks_NativeScaling == GSNativeScaling::Off)
|
if (GSConfig.UserHacks_NativeScaling == GSNativeScaling::Off)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
const GSVector2i draw_size = GSVector2i(m_vt.m_max.p.x - m_vt.m_min.p.x, m_vt.m_max.p.y - m_vt.m_min.p.y);
|
||||||
|
const GSVector2i tex_size = GSVector2i(m_vt.m_max.t.x - m_vt.m_min.t.x, m_vt.m_max.t.y - m_vt.m_min.t.y);
|
||||||
// Check if we're already downscaled and drawing in current size, try not to rescale it.
|
// Check if we're already downscaled and drawing in current size, try not to rescale it.
|
||||||
if (src && src->m_from_target && src->m_from_target->m_downscaled && std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1)
|
if (src && src->m_from_target && (std::abs(draw_size.x - tex_size.x) <= 1 && std::abs(draw_size.y - tex_size.y) <= 1))
|
||||||
return 1;
|
return -1;
|
||||||
|
|
||||||
|
// Try to detect if a game is downscaling/upscaling the image in order to do post processing/bloom effects.
|
||||||
|
const bool is_downscale = (tex_size.x / 2.0f) >= (draw_size.x - 1) && (tex_size.y / 2.0f) >= (draw_size.y - 1);
|
||||||
|
if (is_downscale && draw_size.x >= PCRTCDisplays.GetResolution().x)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
const bool is_upscale = (draw_size.x / 2.0f) >= (tex_size.x - 1) && (draw_size.y / 2.0f) >= (tex_size.y - 1);
|
||||||
|
|
||||||
const bool is_upscale = (draw_size.x / 2.0f) >= tex_size.x && (draw_size.y / 2.0f) >= tex_size.y;
|
|
||||||
const bool target_scale = is_downscale ? true : false;
|
|
||||||
// DMC does a blit in strips with the scissor to keep it inside page boundaries, so that's not technically full coverage
|
// DMC does a blit in strips with the scissor to keep it inside page boundaries, so that's not technically full coverage
|
||||||
// but good enough for what we want.
|
// but good enough for what we want.
|
||||||
const bool no_gaps_or_single_sprite = (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps()));
|
const bool no_gaps_or_single_sprite = (no_gaps || (m_vt.m_primclass == GS_SPRITE_CLASS && SpriteDrawWithoutGaps()));
|
||||||
if (no_gaps_or_single_sprite && m_vt.m_primclass >= GS_TRIANGLE_CLASS && m_context->TEX1.MMAG == 1 && src && src->m_from_target &&
|
if (no_gaps_or_single_sprite && m_vt.m_primclass >= GS_TRIANGLE_CLASS && m_context->TEX1.MMAG == 1 && src && src->m_from_target &&
|
||||||
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp > 8 && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && !IsMipMapDraw() &&
|
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].trbpp > 8 && m_cached_ctx.FRAME.Block() != m_cached_ctx.TEX0.TBP0 && !IsMipMapDraw() &&
|
||||||
((is_upscale && !IsDiscardingDstColor()) || (IsDiscardingDstColor() && is_downscale)))
|
((is_upscale && !IsDiscardingDstColor()) || (((PRIM->ABE && m_context->ALPHA.C == 2 && m_context->ALPHA.FIX == 255) || IsDiscardingDstColor()) && is_downscale)))
|
||||||
{
|
{
|
||||||
GL_INS("%s draw detected - from %dx%d to %dx%d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y);
|
GL_INS("%s draw detected - from %dx%d to %dx%d", is_downscale ? "Downscale" : "Upscale", tex_size.x, tex_size.y, draw_size.x, draw_size.y);
|
||||||
return is_upscale ? 2 : 1;
|
return is_upscale ? 2 : 1;
|
||||||
|
|
|
@ -987,6 +987,7 @@ GSTextureCache::Source* GSTextureCache::LookupDepthSource(const bool is_depth, c
|
||||||
src->m_unscaled_size = dst->m_unscaled_size;
|
src->m_unscaled_size = dst->m_unscaled_size;
|
||||||
src->m_shared_texture = true;
|
src->m_shared_texture = true;
|
||||||
src->m_target = true; // So renderer can check if a conversion is required
|
src->m_target = true; // So renderer can check if a conversion is required
|
||||||
|
src->m_target_direct = true;
|
||||||
src->m_from_target = dst; // avoid complex condition on the renderer
|
src->m_from_target = dst; // avoid complex condition on the renderer
|
||||||
src->m_from_target_TEX0 = dst->m_TEX0;
|
src->m_from_target_TEX0 = dst->m_TEX0;
|
||||||
src->m_32_bits_fmt = dst->m_32_bits_fmt;
|
src->m_32_bits_fmt = dst->m_32_bits_fmt;
|
||||||
|
@ -1746,6 +1747,8 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||||
if (src->m_target && src->m_from_target)
|
if (src->m_target && src->m_from_target)
|
||||||
{
|
{
|
||||||
src->m_valid_alpha_minmax = true;
|
src->m_valid_alpha_minmax = true;
|
||||||
|
if (src->m_target_direct)
|
||||||
|
src->m_scale = src->m_from_target->GetScale();
|
||||||
|
|
||||||
if ((src->m_TEX0.PSM & 0xf) == PSMCT24)
|
if ((src->m_TEX0.PSM & 0xf) == PSMCT24)
|
||||||
{
|
{
|
||||||
|
@ -1797,7 +1800,7 @@ GSVector2i GSTextureCache::ScaleRenderTargetSize(const GSVector2i& sz, float sca
|
||||||
}
|
}
|
||||||
|
|
||||||
GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type,
|
GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type,
|
||||||
bool used, u32 fbmask, bool is_frame, bool preload, bool preserve_rgb, bool preserve_alpha, const GSVector4i draw_rect, bool is_shuffle, bool possible_clear)
|
bool used, u32 fbmask, bool is_frame, bool preload, bool preserve_rgb, bool preserve_alpha, const GSVector4i draw_rect, bool is_shuffle, bool possible_clear, bool preserve_scale)
|
||||||
{
|
{
|
||||||
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
const GSLocalMemory::psm_t& psm_s = GSLocalMemory::m_psm[TEX0.PSM];
|
||||||
const u32 bp = TEX0.TBP0;
|
const u32 bp = TEX0.TBP0;
|
||||||
|
@ -1994,7 +1997,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
dst->m_TEX0.TBP0, dst->m_TEX0.TBW, psm_str(dst->m_TEX0.PSM));
|
dst->m_TEX0.TBP0, dst->m_TEX0.TBW, psm_str(dst->m_TEX0.PSM));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dst->m_scale != scale)
|
if (dst->m_scale != scale && !preserve_scale)
|
||||||
{
|
{
|
||||||
calcRescale(dst);
|
calcRescale(dst);
|
||||||
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :
|
GSTexture* tex = type == RenderTarget ? g_gs_device->CreateRenderTarget(new_scaled_size.x, new_scaled_size.y, GSTexture::Format::Color, clear) :
|
||||||
|
@ -2017,6 +2020,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
dst->m_unscaled_size = new_size;
|
dst->m_unscaled_size = new_size;
|
||||||
dst->m_downscaled = scale == 1.0f;
|
dst->m_downscaled = scale == 1.0f;
|
||||||
}
|
}
|
||||||
|
else if (dst->m_scale != scale)
|
||||||
|
scale = dst->m_scale;
|
||||||
|
|
||||||
// If our RGB was invalidated, we need to pull it from depth.
|
// If our RGB was invalidated, we need to pull it from depth.
|
||||||
// Terminator 3 will reuse our dst_matched target with the RGB masked, then later use the full ARGB area, so we need to update the depth.
|
// Terminator 3 will reuse our dst_matched target with the RGB masked, then later use the full ARGB area, so we need to update the depth.
|
||||||
|
|
|
@ -490,8 +490,8 @@ public:
|
||||||
|
|
||||||
Target* FindTargetOverlap(Target* target, int type, int psm);
|
Target* FindTargetOverlap(Target* target, int type, int psm);
|
||||||
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
|
Target* LookupTarget(GIFRegTEX0 TEX0, const GSVector2i& size, float scale, int type, bool used = true, u32 fbmask = 0,
|
||||||
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
|
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
|
||||||
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false);
|
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false, bool preserve_scale = false);
|
||||||
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
|
Target* CreateTarget(GIFRegTEX0 TEX0, const GSVector2i& size, const GSVector2i& valid_size,float scale, int type, bool used = true, u32 fbmask = 0,
|
||||||
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
|
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_target = true,
|
||||||
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);
|
const GSVector4i draw_rc = GSVector4i::zero(), GSTextureCache::Source* src = nullptr);
|
||||||
|
|
Loading…
Reference in New Issue