mirror of https://github.com/PCSX2/pcsx2.git
GS/HW: Further fixes to HW renderer behaviour
This commit is contained in:
parent
fce7a2652d
commit
ec33d6db6b
|
@ -735,7 +735,7 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba,
|
||||||
|
|
||||||
if (m_context->scissor.in.x & 8)
|
if (m_context->scissor.in.x & 8)
|
||||||
{
|
{
|
||||||
m_context->scissor.in.x &= ~0xf;//m_vt.m_min.p.x;
|
m_context->scissor.in.x &= ~0xf; //m_vt.m_min.p.x;
|
||||||
|
|
||||||
if (half_right_vert)
|
if (half_right_vert)
|
||||||
m_context->scissor.in.x /= 2;
|
m_context->scissor.in.x /= 2;
|
||||||
|
@ -765,6 +765,38 @@ void GSRendererHW::ConvertSpriteTextureShuffle(u32& process_rg, u32& process_ba,
|
||||||
m_vt.m_min.t.x /= 2.0f;
|
m_vt.m_min.t.x /= 2.0f;
|
||||||
m_vt.m_max.t.x = (m_vt.m_max.t.x + 1.9f) / 2.0f;
|
m_vt.m_max.t.x = (m_vt.m_max.t.x + 1.9f) / 2.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Special case used in Call of Duty - World at War where it doubles the height and halves the width, but the height is double doubled.
|
||||||
|
// Check the height of the original texture, if it's half of the draw height, then make it wide instead.
|
||||||
|
if (half_bottom_uv && tex->m_from_target && m_cached_ctx.TEX0.TBW == m_cached_ctx.FRAME.FBW &&
|
||||||
|
tex->m_from_target->m_TEX0.TBW == (m_cached_ctx.TEX0.TBW * 2) && (m_cached_ctx.TEX0.TBW * 64) == floor(m_vt.m_max.t.x))
|
||||||
|
{
|
||||||
|
m_r.z *= 2;
|
||||||
|
m_r.w /= 2;
|
||||||
|
|
||||||
|
m_vt.m_max.t.y /= 2;
|
||||||
|
m_vt.m_max.t.x *= 2;
|
||||||
|
m_vt.m_max.p.y /= 2;
|
||||||
|
m_vt.m_max.p.x *= 2;
|
||||||
|
m_context->scissor.in.w /= 2;
|
||||||
|
m_context->scissor.in.z *= 2;
|
||||||
|
|
||||||
|
v[1].XYZ.X = ((v[m_index.buff[m_index.tail - 1]].XYZ.X - m_context->XYOFFSET.OFX) * 2) + m_context->XYOFFSET.OFX;
|
||||||
|
v[1].XYZ.Y = ((v[m_index.buff[m_index.tail - 1]].XYZ.Y - m_context->XYOFFSET.OFY) / 2) + m_context->XYOFFSET.OFY;
|
||||||
|
|
||||||
|
v[1].U = v[m_index.buff[m_index.tail - 1]].U * 2;
|
||||||
|
v[1].V = v[m_index.buff[m_index.tail - 1]].V / 2;
|
||||||
|
|
||||||
|
v[1].ST.S = v[m_index.buff[m_index.tail - 1]].ST.S * 2;
|
||||||
|
v[1].ST.T = v[m_index.buff[m_index.tail - 1]].ST.T / 2;
|
||||||
|
|
||||||
|
m_vertex.head = m_vertex.tail = m_vertex.next = 2;
|
||||||
|
m_index.tail = 2;
|
||||||
|
|
||||||
|
m_cached_ctx.TEX0.TBW *= 2;
|
||||||
|
m_cached_ctx.FRAME.FBW *= 2;
|
||||||
|
GL_CACHE("Half width/double height shuffle detected, width changed to %d", m_cached_ctx.FRAME.FBW);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
GSVector4 GSRendererHW::RealignTargetTextureCoordinate(const GSTextureCache::Source* tex)
|
GSVector4 GSRendererHW::RealignTargetTextureCoordinate(const GSTextureCache::Source* tex)
|
||||||
|
@ -2868,6 +2900,8 @@ void GSRendererHW::Draw()
|
||||||
else
|
else
|
||||||
FRAME_TEX0.PSM = PSMCT32; // Guess full color if no upcoming hint, it'll fix itself later.
|
FRAME_TEX0.PSM = PSMCT32; // Guess full color if no upcoming hint, it'll fix itself later.
|
||||||
|
|
||||||
|
lookup_rect.x &= ~8; // Get rid of any potential 8 offset;
|
||||||
|
lookup_rect.z += 8; // Get rid of any potential 8 offset;
|
||||||
// This is just for overlap detection, it doesn't matter which direction we do this in
|
// This is just for overlap detection, it doesn't matter which direction we do this in
|
||||||
if (GSLocalMemory::m_psm[FRAME_TEX0.PSM].bpp == 32)
|
if (GSLocalMemory::m_psm[FRAME_TEX0.PSM].bpp == 32)
|
||||||
{
|
{
|
||||||
|
@ -2923,8 +2957,7 @@ void GSRendererHW::Draw()
|
||||||
FRAME_TEX0.TBW = src->m_from_target->m_TEX0.TBW;
|
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,
|
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, lookup_rect, src);
|
||||||
fm, false, force_preload, preserve_rt_color | possible_shuffle, m_r, src);
|
|
||||||
if (!rt) [[unlikely]]
|
if (!rt) [[unlikely]]
|
||||||
{
|
{
|
||||||
GL_INS("ERROR: Failed to create FRAME target, skipping.");
|
GL_INS("ERROR: Failed to create FRAME target, skipping.");
|
||||||
|
@ -4453,7 +4486,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||||
const GSLocalMemory::psm_t frame_psm = GSLocalMemory::m_psm[m_context->FRAME.PSM];
|
const GSLocalMemory::psm_t frame_psm = GSLocalMemory::m_psm[m_context->FRAME.PSM];
|
||||||
const u32 frame_page_offset = std::max(static_cast<int>(((m_r.x / frame_psm.pgs.x) + (m_r.y / frame_psm.pgs.y) * src->m_TEX0.TBW) - m_target_offset), 0);
|
const u32 frame_page_offset = std::max(static_cast<int>(((m_r.x / frame_psm.pgs.x) + (m_r.y / frame_psm.pgs.y) * src->m_TEX0.TBW) - m_target_offset), 0);
|
||||||
m_r = GSVector4i(m_r.x & ~(frame_psm.pgs.x - 1), m_r.y & ~(frame_psm.pgs.y - 1), (m_r.z + (frame_psm.pgs.x - 1)) & ~(frame_psm.pgs.x - 1), (m_r.w + (frame_psm.pgs.y - 1)) & ~(frame_psm.pgs.y - 1));
|
m_r = GSVector4i(m_r.x & ~(frame_psm.pgs.x - 1), m_r.y & ~(frame_psm.pgs.y - 1), (m_r.z + (frame_psm.pgs.x - 1)) & ~(frame_psm.pgs.x - 1), (m_r.w + (frame_psm.pgs.y - 1)) & ~(frame_psm.pgs.y - 1));
|
||||||
m_cached_ctx.FRAME.FBP += frame_page_offset;
|
//m_cached_ctx.FRAME.FBP += frame_page_offset;
|
||||||
m_in_target_draw |= frame_page_offset > 0;
|
m_in_target_draw |= frame_page_offset > 0;
|
||||||
GSVertex* s = &m_vertex.buff[0];
|
GSVertex* s = &m_vertex.buff[0];
|
||||||
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + (m_r.x << 4));
|
s[0].XYZ.X = static_cast<u16>(m_context->XYOFFSET.OFX + (m_r.x << 4));
|
||||||
|
@ -4463,7 +4496,7 @@ __ri bool GSRendererHW::EmulateChannelShuffle(GSTextureCache::Target* src, bool
|
||||||
|
|
||||||
const GSLocalMemory::psm_t tex_psm = GSLocalMemory::m_psm[m_context->TEX0.PSM];
|
const GSLocalMemory::psm_t tex_psm = GSLocalMemory::m_psm[m_context->TEX0.PSM];
|
||||||
const u32 tex_page_offset = (m_vt.m_min.t.x / tex_psm.pgs.x) + (m_vt.m_min.t.y / tex_psm.pgs.y);
|
const u32 tex_page_offset = (m_vt.m_min.t.x / tex_psm.pgs.x) + (m_vt.m_min.t.y / tex_psm.pgs.y);
|
||||||
m_cached_ctx.TEX0.TBP0 += tex_page_offset << 5;
|
//m_cached_ctx.TEX0.TBP0 += tex_page_offset << 5;
|
||||||
s[0].U = m_r.x << 4;
|
s[0].U = m_r.x << 4;
|
||||||
s[1].U = m_r.z << 4;
|
s[1].U = m_r.z << 4;
|
||||||
s[0].V = m_r.y << 4;
|
s[0].V = m_r.y << 4;
|
||||||
|
@ -5707,7 +5740,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
|
||||||
target_region = false;
|
target_region = false;
|
||||||
source_region.bits = 0;
|
source_region.bits = 0;
|
||||||
//copied_rt = tex->m_from_target != nullptr;
|
//copied_rt = tex->m_from_target != nullptr;
|
||||||
if (page_offset && m_in_target_draw)
|
if (m_in_target_draw && (page_offset || frame_diff))
|
||||||
{
|
{
|
||||||
copy_size.x = m_r.width();
|
copy_size.x = m_r.width();
|
||||||
copy_size.y = m_r.height();
|
copy_size.y = m_r.height();
|
||||||
|
|
|
@ -1948,10 +1948,10 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
|
||||||
(static_cast<u32>(min_rect.width()) <= (widthpage_offset * 64))));*/
|
(static_cast<u32>(min_rect.width()) <= (widthpage_offset * 64))));*/
|
||||||
const bool is_aligned_ok = widthpage_offset == 0 || ((min_rect.width() <= static_cast<int>((t->m_TEX0.TBW - widthpage_offset) * 64) && (t->m_TEX0.TBW == TEX0.TBW || TEX0.TBW == 1)) && bp >= t->m_TEX0.TBP0);
|
const bool is_aligned_ok = widthpage_offset == 0 || ((min_rect.width() <= static_cast<int>((t->m_TEX0.TBW - widthpage_offset) * 64) && (t->m_TEX0.TBW == TEX0.TBW || TEX0.TBW == 1)) && bp >= t->m_TEX0.TBP0);
|
||||||
const bool no_target_or_newer = (!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw)));
|
const bool no_target_or_newer = (!dst || ((GSState::s_n - dst->m_last_draw) < (GSState::s_n - t->m_last_draw)));
|
||||||
const bool width_match = (t->m_TEX0.TBW == TEX0.TBW || TEX0.TBW == 1);
|
const bool width_match = (t->m_TEX0.TBW == TEX0.TBW || (TEX0.TBW == 1 && draw_rect.w <= GSLocalMemory::m_psm[t->m_TEX0.PSM].pgs.y));
|
||||||
// if it's a shuffle, some games tend to offset back by a page, such as Tomb Raider, for no disernable reason, but it then causes problems.
|
// if it's a shuffle, some games tend to offset back by a page, such as Tomb Raider, for no disernable reason, but it then causes problems.
|
||||||
// This can also happen horizontally (Catwoman moves everything one page left with shuffles), but this is too messy to deal with right now.
|
// This can also happen horizontally (Catwoman moves everything one page left with shuffles), but this is too messy to deal with right now.
|
||||||
const bool overlaps = t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect) || (is_shuffle && t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect + GSVector4i(0, 0, 0, 32)));
|
const bool overlaps = t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect) || (is_shuffle && GSLocalMemory::m_psm[src->m_TEX0.PSM].bpp == 8 && t->Overlaps(bp, TEX0.TBW, TEX0.PSM, min_rect + GSVector4i(0, 0, 0, 32)));
|
||||||
if (no_target_or_newer && is_aligned_ok && width_match && overlaps)
|
if (no_target_or_newer && is_aligned_ok && width_match && overlaps)
|
||||||
{
|
{
|
||||||
const GSLocalMemory::psm_t& s_psm = GSLocalMemory::m_psm[TEX0.PSM];
|
const GSLocalMemory::psm_t& s_psm = GSLocalMemory::m_psm[TEX0.PSM];
|
||||||
|
|
Loading…
Reference in New Issue