mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Skip target conversion when alpha doesn't exist
This commit is contained in:
parent
12e79cccf6
commit
36865f2930
|
@ -1264,7 +1264,7 @@ static bool GetMoveTargetPair(GSRendererHW& r, GSTextureCache::Target** src, GIF
|
||||||
const int dst_type =
|
const int dst_type =
|
||||||
GSLocalMemory::m_psm[dst_desc.PSM].depth ? GSTextureCache::DepthStencil : GSTextureCache::RenderTarget;
|
GSLocalMemory::m_psm[dst_desc.PSM].depth ? GSTextureCache::DepthStencil : GSTextureCache::RenderTarget;
|
||||||
GSTextureCache::Target* tdst = g_texture_cache->LookupTarget(dst_desc, tsrc->GetUnscaledSize(), tsrc->GetScale(),
|
GSTextureCache::Target* tdst = g_texture_cache->LookupTarget(dst_desc, tsrc->GetUnscaledSize(), tsrc->GetScale(),
|
||||||
dst_type, true, 0, false, false, preserve_target, tsrc->GetUnscaledRect());
|
dst_type, true, 0, false, false, preserve_target, preserve_target, tsrc->GetUnscaledRect());
|
||||||
if (!tdst)
|
if (!tdst)
|
||||||
{
|
{
|
||||||
if (req_target)
|
if (req_target)
|
||||||
|
|
|
@ -1832,11 +1832,14 @@ void GSRendererHW::Draw()
|
||||||
|
|
||||||
const bool process_texture = PRIM->TME && !(PRIM->ABE && m_context->ALPHA.IsBlack() && !m_cached_ctx.TEX0.TCC);
|
const bool process_texture = PRIM->TME && !(PRIM->ABE && m_context->ALPHA.IsBlack() && !m_cached_ctx.TEX0.TCC);
|
||||||
const u32 frame_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
const u32 frame_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
||||||
bool preserve_rt_color =
|
const bool tex_is_rt = (process_texture && m_cached_ctx.TEX0.TBP0 >= m_cached_ctx.FRAME.Block() &&
|
||||||
((!no_rt && (!IsDiscardingDstColor() || !PrimitiveCoversWithoutGaps() || !all_depth_tests_pass)) || // Using Dst Color or draw has gaps
|
m_cached_ctx.TEX0.TBP0 < frame_end_bp);
|
||||||
(process_texture && m_cached_ctx.TEX0.TBP0 >= m_cached_ctx.FRAME.Block() &&
|
const bool not_writing_to_all = (!PrimitiveCoversWithoutGaps() || !all_depth_tests_pass);
|
||||||
m_cached_ctx.TEX0.TBP0 < frame_end_bp)); // Tex is RT
|
const bool preserve_rt_rgb = (!no_rt && (!IsDiscardingDstRGB() || not_writing_to_all));
|
||||||
bool preserve_depth = preserve_rt_color || (!no_ds && (!all_depth_tests_pass || !m_cached_ctx.DepthWrite()));
|
const bool preserve_rt_alpha = (!no_rt && (!IsDiscardingDstAlpha() || not_writing_to_all));
|
||||||
|
bool preserve_rt_color = preserve_rt_rgb || preserve_rt_alpha;
|
||||||
|
bool preserve_depth =
|
||||||
|
preserve_rt_color || (!no_ds && (!all_depth_tests_pass || !m_cached_ctx.DepthWrite() || m_cached_ctx.TEST.ATE));
|
||||||
|
|
||||||
// SW CLUT Render enable.
|
// SW CLUT Render enable.
|
||||||
bool force_preload = GSConfig.PreloadFrameWithGSData;
|
bool force_preload = GSConfig.PreloadFrameWithGSData;
|
||||||
|
@ -2133,6 +2136,7 @@ void GSRendererHW::Draw()
|
||||||
const GSVector4i t_size_rect = GSVector4i::loadh(t_size);
|
const GSVector4i t_size_rect = GSVector4i::loadh(t_size);
|
||||||
|
|
||||||
// Ensure draw rect is clamped to framebuffer size. Necessary for updating valid area.
|
// Ensure draw rect is clamped to framebuffer size. Necessary for updating valid area.
|
||||||
|
const GSVector4i unclamped_draw_rect = m_r;
|
||||||
m_r = m_r.rintersect(t_size_rect);
|
m_r = m_r.rintersect(t_size_rect);
|
||||||
|
|
||||||
float target_scale = GetTextureScaleFactor();
|
float target_scale = GetTextureScaleFactor();
|
||||||
|
@ -2163,7 +2167,7 @@ void GSRendererHW::Draw()
|
||||||
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps();
|
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && PrimitiveCoversWithoutGaps();
|
||||||
const bool is_clear = is_possible_mem_clear && is_square;
|
const bool is_clear = is_possible_mem_clear && is_square;
|
||||||
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_color, m_r);
|
fm, false, force_preload, preserve_rt_rgb, preserve_rt_alpha, unclamped_draw_rect);
|
||||||
|
|
||||||
// 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)
|
||||||
|
@ -2197,7 +2201,7 @@ void GSRendererHW::Draw()
|
||||||
ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM;
|
ZBUF_TEX0.PSM = m_cached_ctx.ZBUF.PSM;
|
||||||
|
|
||||||
ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
|
ds = g_texture_cache->LookupTarget(ZBUF_TEX0, t_size, target_scale, GSTextureCache::DepthStencil,
|
||||||
m_cached_ctx.DepthWrite(), 0, false, force_preload, preserve_depth, m_r);
|
m_cached_ctx.DepthWrite(), 0, false, force_preload, preserve_depth, preserve_depth, unclamped_draw_rect);
|
||||||
if (!ds)
|
if (!ds)
|
||||||
{
|
{
|
||||||
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
|
ds = g_texture_cache->CreateTarget(ZBUF_TEX0, t_size, GetValidSize(src), target_scale, GSTextureCache::DepthStencil,
|
||||||
|
@ -5814,7 +5818,25 @@ bool GSRendererHW::IsDiscardingDstColor()
|
||||||
(!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsBlack()) && // no blending or writing black
|
(!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsBlack()) && // no blending or writing black
|
||||||
!m_cached_ctx.TEST.ATE && // not testing alpha (might discard some pixels)
|
!m_cached_ctx.TEST.ATE && // not testing alpha (might discard some pixels)
|
||||||
!m_cached_ctx.TEST.DATE && // not reading alpha
|
!m_cached_ctx.TEST.DATE && // not reading alpha
|
||||||
(m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0); // no channels masked
|
(m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) == 0); // no channels masked
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSRendererHW::IsDiscardingDstRGB()
|
||||||
|
{
|
||||||
|
return ((!PRIM->ABE || IsOpaque() || m_context->ALPHA.IsBlack()) && // no blending or writing black
|
||||||
|
!m_cached_ctx.TEST.ATE && // not testing alpha (might discard some pixels)
|
||||||
|
!m_cached_ctx.TEST.DATE && // not reading alpha
|
||||||
|
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFFFFFFu) ==
|
||||||
|
0); // RGB isn't masked
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GSRendererHW::IsDiscardingDstAlpha()
|
||||||
|
{
|
||||||
|
return ((!PRIM->ABE || m_context->ALPHA.C != 1) && // not using Ad
|
||||||
|
!m_cached_ctx.TEST.ATE && // not testing alpha (might discard some pixels)
|
||||||
|
!m_cached_ctx.TEST.DATE && // not reading alpha
|
||||||
|
((m_cached_ctx.FRAME.FBMSK & GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].fmsk) & 0xFF000000u) ==
|
||||||
|
0); // alpha isn't masked
|
||||||
}
|
}
|
||||||
|
|
||||||
bool GSRendererHW::PrimitiveCoversWithoutGaps()
|
bool GSRendererHW::PrimitiveCoversWithoutGaps()
|
||||||
|
|
|
@ -62,6 +62,8 @@ private:
|
||||||
u32 GetConstantDirectWriteMemClearColor() const;
|
u32 GetConstantDirectWriteMemClearColor() const;
|
||||||
bool IsReallyDithered() const;
|
bool IsReallyDithered() const;
|
||||||
bool IsDiscardingDstColor();
|
bool IsDiscardingDstColor();
|
||||||
|
bool IsDiscardingDstRGB();
|
||||||
|
bool IsDiscardingDstAlpha();
|
||||||
bool PrimitiveCoversWithoutGaps();
|
bool PrimitiveCoversWithoutGaps();
|
||||||
|
|
||||||
enum class CLUTDrawTestResult
|
enum class CLUTDrawTestResult
|
||||||
|
|
|
@ -1241,7 +1241,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_target, const GSVector4i draw_rect)
|
bool used, u32 fbmask, bool is_frame, bool preload, bool preserve_rgb, bool preserve_alpha, const GSVector4i draw_rect)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -1393,6 +1393,7 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
}
|
}
|
||||||
|
|
||||||
// If our RGB was invalidated, we need to pull it from depth.
|
// If our RGB was invalidated, we need to pull it from depth.
|
||||||
|
const bool preserve_target = preserve_rgb || preserve_alpha;
|
||||||
if (type == RenderTarget && (preserve_target || !dst->m_valid.rintersect(draw_rect).eq(dst->m_valid)) &&
|
if (type == RenderTarget && (preserve_target || !dst->m_valid.rintersect(draw_rect).eq(dst->m_valid)) &&
|
||||||
!dst->m_valid_rgb && !FullRectDirty(dst, 0x7) &&
|
!dst->m_valid_rgb && !FullRectDirty(dst, 0x7) &&
|
||||||
(GSLocalMemory::m_psm[TEX0.PSM].trbpp < 24 || fbmask != 0x00FFFFFFu))
|
(GSLocalMemory::m_psm[TEX0.PSM].trbpp < 24 || fbmask != 0x00FFFFFFu))
|
||||||
|
@ -1479,6 +1480,15 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
if (dst_match)
|
if (dst_match)
|
||||||
{
|
{
|
||||||
calcRescale(dst_match);
|
calcRescale(dst_match);
|
||||||
|
|
||||||
|
// If we don't need A, and the existing target doesn't have valid alpha, don't bother converting it.
|
||||||
|
const bool has_alpha = dst_match->m_valid_alpha_low || dst_match->m_valid_alpha_high;
|
||||||
|
const bool preserve_target = (preserve_rgb || (preserve_alpha && has_alpha)) ||
|
||||||
|
!draw_rect.rintersect(dst_match->m_valid).eq(dst_match->m_valid);
|
||||||
|
|
||||||
|
// Clear instead of invalidating if there is anything which isn't touched.
|
||||||
|
clear |= (!preserve_target && fbmask != 0);
|
||||||
|
|
||||||
dst = Target::Create(TEX0, new_size.x, new_size.y, scale, type, clear);
|
dst = Target::Create(TEX0, new_size.x, new_size.y, scale, type, clear);
|
||||||
if (!dst)
|
if (!dst)
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -1509,7 +1519,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
shader = (fmt_16_bits) ? ShaderConvert::FLOAT16_TO_RGB5A1 : ShaderConvert::FLOAT32_TO_RGBA8;
|
shader = (fmt_16_bits) ? ShaderConvert::FLOAT16_TO_RGB5A1 : ShaderConvert::FLOAT32_TO_RGBA8;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!preserve_target && draw_rect.rintersect(dst_match->m_valid).eq(dst_match->m_valid))
|
|
||||||
|
if (!preserve_target)
|
||||||
{
|
{
|
||||||
GL_INS("TC: Not converting existing %s[%x] because it's fully overwritten.", to_string(!type), dst->m_TEX0.TBP0);
|
GL_INS("TC: Not converting existing %s[%x] because it's fully overwritten.", to_string(!type), dst->m_TEX0.TBP0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -478,7 +478,7 @@ 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_target = true,
|
bool is_frame = false, bool preload = GSConfig.PreloadFrameWithGSData, bool preserve_rgb = true, bool preserve_alpha = true,
|
||||||
const GSVector4i draw_rc = GSVector4i::zero());
|
const GSVector4i draw_rc = GSVector4i::zero());
|
||||||
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,
|
||||||
|
|
Loading…
Reference in New Issue