mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Further RT in RT changes to improve compatibility
This commit is contained in:
parent
8865ad90ff
commit
3b17ccac36
|
@ -2736,136 +2736,6 @@ void GSRendererHW::Draw()
|
||||||
m_in_target_draw = false;
|
m_in_target_draw = false;
|
||||||
m_target_offset = 0;
|
m_target_offset = 0;
|
||||||
|
|
||||||
if (!no_rt)
|
|
||||||
{
|
|
||||||
const bool possible_shuffle = draw_sprite_tex && (((src && src->m_target && src->m_from_target && src->m_from_target->m_32_bits_fmt) &&
|
|
||||||
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
|
||||||
IsPossibleChannelShuffle());
|
|
||||||
|
|
||||||
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
|
||||||
FRAME_TEX0.U64 = 0;
|
|
||||||
FRAME_TEX0.TBP0 = ((m_last_channel_shuffle_end_block + 1) == m_cached_ctx.FRAME.Block() && possible_shuffle) ? m_last_channel_shuffle_fbp : m_cached_ctx.FRAME.Block();
|
|
||||||
FRAME_TEX0.TBW = (possible_shuffle && (m_last_channel_shuffle_end_block + 1) && src->m_target) ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
|
||||||
FRAME_TEX0.PSM = m_cached_ctx.FRAME.PSM;
|
|
||||||
|
|
||||||
|
|
||||||
// Don't clamp on shuffle, the height cache may troll us with the REAL height.
|
|
||||||
if (!possible_shuffle && m_split_texture_shuffle_pages == 0)
|
|
||||||
m_r = m_r.rintersect(t_size_rect);
|
|
||||||
|
|
||||||
// Normally we would use 1024 here to match the clear above, but The Godfather does a 1023x1023 draw instead
|
|
||||||
// (very close to 1024x1024, but apparently the GS rounds down..). So, catch that here, we don't want to
|
|
||||||
// create that target, because the clear isn't black, it'll hang around and never get invalidated.
|
|
||||||
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && m_primitive_covers_without_gaps == NoGapsType::FullCover;
|
|
||||||
const bool is_clear = is_possible_mem_clear && is_square;
|
|
||||||
|
|
||||||
// Preserve downscaled target when copying directly from a downscaled target, or it's a normal draw using a downscaled target. Clears that are drawing to the target can also preserve size.
|
|
||||||
// Of course if this size is different (in width) or this is a shuffle happening, this will be bypassed.
|
|
||||||
const bool preserve_downscale_draw = scale_draw < 0 || (scale_draw == 0 && ((src && src->m_from_target && src->m_from_target->m_downscaled) || is_possible_mem_clear == ClearType::ClearWithDraw));
|
|
||||||
|
|
||||||
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal && !possible_shuffle) ? GetTextureScaleFactor() : 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(),
|
|
||||||
GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && preserve_downscale_draw && is_possible_mem_clear != ClearType::NormalClear, src);
|
|
||||||
|
|
||||||
// Draw skipped because it was a clear and there was no target.
|
|
||||||
if (!rt)
|
|
||||||
{
|
|
||||||
if (is_clear)
|
|
||||||
{
|
|
||||||
GL_INS("Clear draw with no target, skipping.");
|
|
||||||
|
|
||||||
const bool is_zero_color_clear = (GetConstantDirectWriteMemClearColor() == 0 && !preserve_rt_color);
|
|
||||||
const bool is_zero_depth_clear = (GetConstantDirectWriteMemClearDepth() == 0 && !preserve_depth);
|
|
||||||
const u32 rt_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(
|
|
||||||
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
|
||||||
const u32 ds_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(
|
|
||||||
m_cached_ctx.ZBUF.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.ZBUF.PSM, m_r);
|
|
||||||
TryGSMemClear(no_rt, preserve_rt_color, is_zero_color_clear, rt_end_bp,
|
|
||||||
no_ds, preserve_depth, is_zero_depth_clear, ds_end_bp);
|
|
||||||
|
|
||||||
CleanupDraw(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else if (IsPageCopy() && src->m_from_target && m_cached_ctx.TEX0.TBP0 >= src->m_from_target->m_TEX0.TBP0)
|
|
||||||
{
|
|
||||||
FRAME_TEX0.TBW = src->m_from_target->m_TEX0.TBW;
|
|
||||||
}
|
|
||||||
|
|
||||||
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), (scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale, GSTextureCache::RenderTarget, true,
|
|
||||||
fm, false, force_preload, preserve_rt_color | possible_shuffle, m_r, src);
|
|
||||||
if (!rt) [[unlikely]]
|
|
||||||
{
|
|
||||||
GL_INS("ERROR: Failed to create FRAME target, skipping.");
|
|
||||||
CleanupDraw(true);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block()) // Must have done rt in rt
|
|
||||||
{
|
|
||||||
GSVertex* v = &m_vertex.buff[0];
|
|
||||||
int vertical_offset = ((std::abs(static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5) / std::max(rt->m_TEX0.TBW, 1U)) * frame_psm.pgs.y; // I know I could just not shift it..
|
|
||||||
|
|
||||||
const int horizontal_offset = (std::abs(static_cast<int>((m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5) % std::max(rt->m_TEX0.TBW, 1U)) * frame_psm.pgs.x;
|
|
||||||
// Used to reduce the offset made later in channel shuffles
|
|
||||||
m_target_offset = std::abs(static_cast<int>((m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5);
|
|
||||||
|
|
||||||
for (u32 i = 0; i < m_vertex.tail; i++)
|
|
||||||
{
|
|
||||||
v[i].XYZ.Y += vertical_offset << 4;
|
|
||||||
v[i].XYZ.X += horizontal_offset << 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_context->scissor.in.x += horizontal_offset;
|
|
||||||
m_context->scissor.in.z += horizontal_offset;
|
|
||||||
m_context->scissor.in.y += vertical_offset;
|
|
||||||
m_context->scissor.in.w += vertical_offset;
|
|
||||||
m_r.y += vertical_offset;
|
|
||||||
m_r.w += vertical_offset;
|
|
||||||
m_r.x += horizontal_offset;
|
|
||||||
m_r.z += horizontal_offset;
|
|
||||||
m_in_target_draw = true;
|
|
||||||
m_vt.m_min.p.x += horizontal_offset;
|
|
||||||
m_vt.m_max.p.x += horizontal_offset;
|
|
||||||
m_vt.m_min.p.y += vertical_offset;
|
|
||||||
m_vt.m_max.p.y += vertical_offset;
|
|
||||||
t_size.x = rt->m_unscaled_size.x - horizontal_offset;
|
|
||||||
t_size.y = rt->m_unscaled_size.y - vertical_offset;
|
|
||||||
|
|
||||||
if (t_size.y <= 0)
|
|
||||||
{
|
|
||||||
u32 new_height = m_r.w;
|
|
||||||
|
|
||||||
//DevCon.Warning("Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
|
|
||||||
rt->ResizeTexture(rt->m_unscaled_size.x, new_height);
|
|
||||||
rt->UpdateValidity(m_r, true);
|
|
||||||
rt->UpdateDrawn(m_r, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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.
|
|
||||||
preserve_rt_alpha |= (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp == 24 && rt->HasValidAlpha());
|
|
||||||
preserve_rt_color = preserve_rt_rgb || preserve_rt_alpha;
|
|
||||||
|
|
||||||
if (m_channel_shuffle)
|
|
||||||
{
|
|
||||||
m_last_channel_shuffle_fbp = rt->m_TEX0.TBP0;
|
|
||||||
|
|
||||||
// If it's a new target, we don't know where the end is as it's starting on a shuffle, so just do every shuffle following.
|
|
||||||
m_last_channel_shuffle_end_block = (rt->m_last_draw >= s_n) ? (MAX_BLOCKS - 1) : (rt->m_end_block < rt->m_TEX0.TBP0 ? (rt->m_end_block + MAX_BLOCKS) : rt->m_end_block);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
m_last_channel_shuffle_end_block = 0xFFFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
GSTextureCache::Target* ds = nullptr;
|
GSTextureCache::Target* ds = nullptr;
|
||||||
GIFRegTEX0 ZBUF_TEX0;
|
GIFRegTEX0 ZBUF_TEX0;
|
||||||
if (!no_ds)
|
if (!no_ds)
|
||||||
|
@ -2876,20 +2746,21 @@ 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, preserve_depth, unclamped_draw_rect, IsPossibleChannelShuffle(), is_possible_mem_clear && ZBUF_TEX0.TBP0 != m_cached_ctx.FRAME.Block());
|
m_cached_ctx.DepthWrite(), 0, false, force_preload, preserve_depth, preserve_depth, unclamped_draw_rect, IsPossibleChannelShuffle(), is_possible_mem_clear && ZBUF_TEX0.TBP0 != m_cached_ctx.FRAME.Block(), false,
|
||||||
|
src, -1);
|
||||||
|
|
||||||
ZBUF_TEX0.TBW = m_channel_shuffle ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
ZBUF_TEX0.TBW = m_channel_shuffle ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
||||||
|
|
||||||
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,
|
||||||
true, 0, false, force_preload, preserve_depth, m_r, src);
|
true, 0, false, force_preload, preserve_depth, m_r, src);
|
||||||
if (!ds) [[unlikely]]
|
if (!ds) [[unlikely]]
|
||||||
{
|
{
|
||||||
GL_INS("ERROR: Failed to create ZBUF target, skipping.");
|
GL_INS("ERROR: Failed to create ZBUF target, skipping.");
|
||||||
CleanupDraw(true);
|
CleanupDraw(true);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -2934,6 +2805,143 @@ void GSRendererHW::Draw()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!no_rt)
|
||||||
|
{
|
||||||
|
const bool possible_shuffle = draw_sprite_tex && (((src && src->m_target && src->m_from_target && src->m_from_target->m_32_bits_fmt) &&
|
||||||
|
GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].bpp == 16) ||
|
||||||
|
IsPossibleChannelShuffle());
|
||||||
|
|
||||||
|
// FBW is going to be wrong for channel shuffling into a new target, so take it from the source.
|
||||||
|
FRAME_TEX0.U64 = 0;
|
||||||
|
FRAME_TEX0.TBP0 = ((m_last_channel_shuffle_end_block + 1) == m_cached_ctx.FRAME.Block() && possible_shuffle) ? m_last_channel_shuffle_fbp : m_cached_ctx.FRAME.Block();
|
||||||
|
FRAME_TEX0.TBW = (possible_shuffle && (m_last_channel_shuffle_end_block + 1) && src->m_target) ? src->m_from_target_TEX0.TBW : m_cached_ctx.FRAME.FBW;
|
||||||
|
FRAME_TEX0.PSM = m_cached_ctx.FRAME.PSM;
|
||||||
|
|
||||||
|
|
||||||
|
// Don't clamp on shuffle, the height cache may troll us with the REAL height.
|
||||||
|
if (!possible_shuffle && m_split_texture_shuffle_pages == 0)
|
||||||
|
m_r = m_r.rintersect(t_size_rect);
|
||||||
|
|
||||||
|
// Normally we would use 1024 here to match the clear above, but The Godfather does a 1023x1023 draw instead
|
||||||
|
// (very close to 1024x1024, but apparently the GS rounds down..). So, catch that here, we don't want to
|
||||||
|
// create that target, because the clear isn't black, it'll hang around and never get invalidated.
|
||||||
|
const bool is_square = (t_size.y == t_size.x) && m_r.w >= 1023 && m_primitive_covers_without_gaps == NoGapsType::FullCover;
|
||||||
|
const bool is_clear = is_possible_mem_clear && is_square;
|
||||||
|
|
||||||
|
// Preserve downscaled target when copying directly from a downscaled target, or it's a normal draw using a downscaled target. Clears that are drawing to the target can also preserve size.
|
||||||
|
// Of course if this size is different (in width) or this is a shuffle happening, this will be bypassed.
|
||||||
|
const bool preserve_downscale_draw = scale_draw < 0 || (scale_draw == 0 && ((src && src->m_from_target && src->m_from_target->m_downscaled) || is_possible_mem_clear == ClearType::ClearWithDraw));
|
||||||
|
|
||||||
|
rt = g_texture_cache->LookupTarget(FRAME_TEX0, t_size, ((src && src->m_scale != 1) && GSConfig.UserHacks_NativeScaling == GSNativeScaling::Normal && !possible_shuffle) ? GetTextureScaleFactor() : 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(),
|
||||||
|
GSConfig.UserHacks_NativeScaling != GSNativeScaling::Off && preserve_downscale_draw && is_possible_mem_clear != ClearType::NormalClear, src, no_ds ? -1 : (m_cached_ctx.ZBUF.Block() - ds->m_TEX0.TBP0));
|
||||||
|
|
||||||
|
// Draw skipped because it was a clear and there was no target.
|
||||||
|
if (!rt)
|
||||||
|
{
|
||||||
|
if (is_clear)
|
||||||
|
{
|
||||||
|
GL_INS("Clear draw with no target, skipping.");
|
||||||
|
|
||||||
|
const bool is_zero_color_clear = (GetConstantDirectWriteMemClearColor() == 0 && !preserve_rt_color);
|
||||||
|
const bool is_zero_depth_clear = (GetConstantDirectWriteMemClearDepth() == 0 && !preserve_depth);
|
||||||
|
const u32 rt_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(
|
||||||
|
m_cached_ctx.FRAME.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.PSM, m_r);
|
||||||
|
const u32 ds_end_bp = GSLocalMemory::GetUnwrappedEndBlockAddress(
|
||||||
|
m_cached_ctx.ZBUF.Block(), m_cached_ctx.FRAME.FBW, m_cached_ctx.ZBUF.PSM, m_r);
|
||||||
|
TryGSMemClear(no_rt, preserve_rt_color, is_zero_color_clear, rt_end_bp,
|
||||||
|
no_ds, preserve_depth, is_zero_depth_clear, ds_end_bp);
|
||||||
|
|
||||||
|
CleanupDraw(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else if (IsPageCopy() && src->m_from_target && m_cached_ctx.TEX0.TBP0 >= src->m_from_target->m_TEX0.TBP0)
|
||||||
|
{
|
||||||
|
FRAME_TEX0.TBW = src->m_from_target->m_TEX0.TBW;
|
||||||
|
}
|
||||||
|
|
||||||
|
rt = g_texture_cache->CreateTarget(FRAME_TEX0, t_size, GetValidSize(src), (scale_draw < 0 && is_possible_mem_clear != ClearType::NormalClear) ? src->m_from_target->GetScale() : target_scale, GSTextureCache::RenderTarget, true,
|
||||||
|
fm, false, force_preload, preserve_rt_color | possible_shuffle, m_r, src);
|
||||||
|
if (!rt) [[unlikely]]
|
||||||
|
{
|
||||||
|
GL_INS("ERROR: Failed to create FRAME target, skipping.");
|
||||||
|
CleanupDraw(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (rt->m_TEX0.TBP0 != m_cached_ctx.FRAME.Block())
|
||||||
|
{
|
||||||
|
GSVertex* v = &m_vertex.buff[0];
|
||||||
|
int vertical_offset = ((std::abs(static_cast<int>(m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5) / std::max(rt->m_TEX0.TBW, 1U)) * frame_psm.pgs.y; // I know I could just not shift it..
|
||||||
|
|
||||||
|
const int horizontal_offset = (std::abs(static_cast<int>((m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5) % std::max(rt->m_TEX0.TBW, 1U)) * frame_psm.pgs.x;
|
||||||
|
// Used to reduce the offset made later in channel shuffles
|
||||||
|
m_target_offset = std::abs(static_cast<int>((m_cached_ctx.FRAME.Block() - rt->m_TEX0.TBP0)) >> 5);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < m_vertex.tail; i++)
|
||||||
|
{
|
||||||
|
v[i].XYZ.Y += vertical_offset << 4;
|
||||||
|
v[i].XYZ.X += horizontal_offset << 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_context->scissor.in.x += horizontal_offset;
|
||||||
|
m_context->scissor.in.z += horizontal_offset;
|
||||||
|
m_context->scissor.in.y += vertical_offset;
|
||||||
|
m_context->scissor.in.w += vertical_offset;
|
||||||
|
m_r.y += vertical_offset;
|
||||||
|
m_r.w += vertical_offset;
|
||||||
|
m_r.x += horizontal_offset;
|
||||||
|
m_r.z += horizontal_offset;
|
||||||
|
m_in_target_draw = true;
|
||||||
|
m_vt.m_min.p.x += horizontal_offset;
|
||||||
|
m_vt.m_max.p.x += horizontal_offset;
|
||||||
|
m_vt.m_min.p.y += vertical_offset;
|
||||||
|
m_vt.m_max.p.y += vertical_offset;
|
||||||
|
|
||||||
|
t_size.x = rt->m_unscaled_size.x - horizontal_offset;
|
||||||
|
t_size.y = rt->m_unscaled_size.y - vertical_offset;
|
||||||
|
|
||||||
|
// Don't resize if the BPP don't match.
|
||||||
|
if (frame_psm.bpp == GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp)
|
||||||
|
{
|
||||||
|
if (t_size.y <= 0)
|
||||||
|
{
|
||||||
|
u32 new_height = m_r.w;
|
||||||
|
|
||||||
|
if (possible_shuffle && std::abs(static_cast<s16>(GSLocalMemory::m_psm[rt->m_TEX0.PSM].bpp - GSLocalMemory::m_psm[TEX0.PSM].bpp)) == 16)
|
||||||
|
new_height /= 2;
|
||||||
|
//DevCon.Warning("Resizing texture %d x %d draw %d", rt->m_unscaled_size.x, new_height, s_n);
|
||||||
|
rt->ResizeTexture(rt->m_unscaled_size.x, new_height);
|
||||||
|
rt->UpdateValidity(m_r, true);
|
||||||
|
rt->UpdateDrawn(m_r, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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.
|
||||||
|
preserve_rt_alpha |= (GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].trbpp == 24 && rt->HasValidAlpha());
|
||||||
|
preserve_rt_color = preserve_rt_rgb || preserve_rt_alpha;
|
||||||
|
|
||||||
|
if (m_channel_shuffle)
|
||||||
|
{
|
||||||
|
m_last_channel_shuffle_fbp = rt->m_TEX0.TBP0;
|
||||||
|
|
||||||
|
// If it's a new target, we don't know where the end is as it's starting on a shuffle, so just do every shuffle following.
|
||||||
|
m_last_channel_shuffle_end_block = (rt->m_last_draw >= s_n) ? (MAX_BLOCKS - 1) : (rt->m_end_block < rt->m_TEX0.TBP0 ? (rt->m_end_block + MAX_BLOCKS) : rt->m_end_block);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
m_last_channel_shuffle_end_block = 0xFFFF;
|
||||||
|
}
|
||||||
|
|
||||||
if (m_process_texture)
|
if (m_process_texture)
|
||||||
{
|
{
|
||||||
GIFRegCLAMP MIP_CLAMP = m_cached_ctx.CLAMP;
|
GIFRegCLAMP MIP_CLAMP = m_cached_ctx.CLAMP;
|
||||||
|
@ -4161,7 +4169,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||||
// Performance GPU note: it could be wise to reduce the size to
|
// Performance GPU note: it could be wise to reduce the size to
|
||||||
// the rendered size of the framebuffer
|
// the rendered size of the framebuffer
|
||||||
|
|
||||||
if (!m_in_target_draw && (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || NextDrawMatchesShuffle()))
|
if (GSConfig.UserHacks_TextureInsideRt == GSTextureInRtMode::Disabled || (!m_in_target_draw && NextDrawMatchesShuffle()))
|
||||||
{
|
{
|
||||||
GSVertex* s = &m_vertex.buff[0];
|
GSVertex* s = &m_vertex.buff[0];
|
||||||
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + 0);
|
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + 0);
|
||||||
|
|
|
@ -1800,7 +1800,8 @@ 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 preserve_scale, GSTextureCache::Source* src)
|
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, GSTextureCache::Source* src, int offset)
|
||||||
{
|
{
|
||||||
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;
|
||||||
|
@ -1898,8 +1899,11 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Probably pointing to half way through the target
|
// Probably pointing to half way through the target
|
||||||
else if(GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
|
else if (GSConfig.UserHacks_TextureInsideRt >= GSTextureInRtMode::InsideTargets)
|
||||||
{
|
{
|
||||||
|
if (offset != -1 && (bp - t->m_TEX0.TBP0) != offset)
|
||||||
|
continue;
|
||||||
|
|
||||||
const u32 widthpage_offset = (std::abs(static_cast<int>(bp - t->m_TEX0.TBP0)) >> 5) % std::max(t->m_TEX0.TBW, 1U);
|
const u32 widthpage_offset = (std::abs(static_cast<int>(bp - t->m_TEX0.TBP0)) >> 5) % std::max(t->m_TEX0.TBW, 1U);
|
||||||
const bool is_aligned_ok = widthpage_offset == 0 || ((widthpage_offset + TEX0.TBW) <= t->m_TEX0.TBW) || min_rect.width() <= 64 || (widthpage_offset == (t->m_TEX0.TBW >> 1) && (static_cast<u32>(min_rect.width()) <= (widthpage_offset * 64)));
|
const bool is_aligned_ok = widthpage_offset == 0 || ((widthpage_offset + TEX0.TBW) <= t->m_TEX0.TBW) || min_rect.width() <= 64 || (widthpage_offset == (t->m_TEX0.TBW >> 1) && (static_cast<u32>(min_rect.width()) <= (widthpage_offset * 64)));
|
||||||
if ((!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))) && is_aligned_ok && (t->m_TEX0.TBW == TEX0.TBW || (TEX0.TBW == 1 && t->m_TEX0.TBW > 1)) && t->Inside(bp, TEX0.TBW, TEX0.PSM, min_rect))
|
if ((!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw))) && is_aligned_ok && (t->m_TEX0.TBW == TEX0.TBW || (TEX0.TBW == 1 && t->m_TEX0.TBW > 1)) && t->Inside(bp, TEX0.TBW, TEX0.PSM, min_rect))
|
||||||
|
@ -2083,6 +2087,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
}
|
}
|
||||||
else if (!is_shuffle && std::abs(static_cast<s16>(GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp - GSLocalMemory::m_psm[TEX0.PSM].bpp)) == 16)
|
else if (!is_shuffle && std::abs(static_cast<s16>(GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp - GSLocalMemory::m_psm[TEX0.PSM].bpp)) == 16)
|
||||||
{
|
{
|
||||||
|
dst->Update(false);
|
||||||
|
|
||||||
const bool scale_down = GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp > GSLocalMemory::m_psm[TEX0.PSM].bpp;
|
const bool scale_down = GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp > GSLocalMemory::m_psm[TEX0.PSM].bpp;
|
||||||
new_size = dst->m_unscaled_size;
|
new_size = dst->m_unscaled_size;
|
||||||
new_scaled_size = ScaleRenderTargetSize(dst->m_unscaled_size, scale);
|
new_scaled_size = ScaleRenderTargetSize(dst->m_unscaled_size, scale);
|
||||||
|
@ -2340,6 +2346,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
dst->m_valid_alpha_high = dst_match->m_valid_alpha_high; //&& psm_s.trbpp != 24;
|
dst->m_valid_alpha_high = dst_match->m_valid_alpha_high; //&& psm_s.trbpp != 24;
|
||||||
dst->m_valid_rgb = dst_match->m_valid_rgb;
|
dst->m_valid_rgb = dst_match->m_valid_rgb;
|
||||||
dst->m_was_dst_matched = true;
|
dst->m_was_dst_matched = true;
|
||||||
|
dst_match->m_was_dst_matched = true;
|
||||||
|
dst_match->m_valid_rgb = false;
|
||||||
|
|
||||||
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[dst_match->m_TEX0.PSM].bpp > 16)
|
if (GSLocalMemory::m_psm[dst->m_TEX0.PSM].bpp == 16 && GSLocalMemory::m_psm[dst_match->m_TEX0.PSM].bpp > 16)
|
||||||
dst->m_TEX0.TBW = dst_match->m_TEX0.TBW; // Be careful of shuffles of the depth as C16, but using a buffer width of 16 (Mercenaries).
|
dst->m_TEX0.TBW = dst_match->m_TEX0.TBW; // Be careful of shuffles of the depth as C16, but using a buffer width of 16 (Mercenaries).
|
||||||
|
@ -3174,6 +3182,17 @@ void GSTextureCache::InvalidateContainedTargets(u32 start_bp, u32 end_bp, u32 wr
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Not covering the whole target, and a different format, so just dirty it.
|
||||||
|
if (start_bp == t->m_TEX0.TBP0 && (t->UnwrappedEndBlock() > end_bp) && write_psm != t->m_TEX0.PSM)
|
||||||
|
{
|
||||||
|
const GSLocalMemory::psm_t& target_psm = GSLocalMemory::m_psm[write_psm];
|
||||||
|
u32 total_pages = (end_bp - t->m_TEX0.TBP0) >> 5;
|
||||||
|
GSVector4i dirty_area = GSVector4i(0, 0, t->m_valid.z, (total_pages / t->m_TEX0.TBW) * target_psm.pgs.y);
|
||||||
|
InvalidateVideoMem(g_gs_renderer->m_mem.GetOffset(t->m_TEX0.TBP0, t->m_TEX0.TBW, write_psm), dirty_area, true);
|
||||||
|
++i;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
InvalidateSourcesFromTarget(t);
|
InvalidateSourcesFromTarget(t);
|
||||||
|
|
||||||
t->m_valid_alpha_low &= preserve_alpha;
|
t->m_valid_alpha_low &= preserve_alpha;
|
||||||
|
@ -4588,9 +4607,9 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hack = false;
|
bool hack = false;
|
||||||
bool channel_shuffle = false;
|
bool channel_shuffle = dst && (TEX0.PSM == PSMT8) && (GSRendererHW::GetInstance()->TestChannelShuffle(dst));
|
||||||
|
|
||||||
if (dst && (x_offset != 0 || y_offset != 0))
|
if (dst && (x_offset != 0 || y_offset != 0) && (TEX0.PSM != PSMT8 || channel_shuffle))
|
||||||
{
|
{
|
||||||
const float scale = dst->m_scale;
|
const float scale = dst->m_scale;
|
||||||
const int x = static_cast<int>(scale * x_offset);
|
const int x = static_cast<int>(scale * x_offset);
|
||||||
|
@ -4653,8 +4672,6 @@ GSTextureCache::Source* GSTextureCache::CreateSource(const GIFRegTEX0& TEX0, con
|
||||||
src->m_texture = dst->m_texture;
|
src->m_texture = dst->m_texture;
|
||||||
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;
|
||||||
|
|
||||||
channel_shuffle = GSRendererHW::GetInstance()->TestChannelShuffle(dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Invalidate immediately on recursive draws, because if we don't here, InvalidateVideoMem() will.
|
// Invalidate immediately on recursive draws, because if we don't here, InvalidateVideoMem() will.
|
||||||
|
|
|
@ -491,7 +491,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_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, bool preserve_scale = false, GSTextureCache::Source* src = nullptr);
|
const GSVector4i draw_rc = GSVector4i::zero(), bool is_shuffle = false, bool possible_clear = false, bool preserve_scale = false, GSTextureCache::Source* src = nullptr, int offset = -1);
|
||||||
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