Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -861,7 +861,8 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
const bool bilinear = m_vt.IsRealLinear();

// Copy the attributes from the provoking vertex.
GSVertex v_default = primclass == GS_SPRITE_CLASS ? m_vertex.buff[1] : m_vertex.buff[2];
GSVertex v_default = primclass == GS_SPRITE_CLASS ? m_vertex.buff[m_index.buff[1]] :
m_vertex.buff[m_index.buff[2]];

const auto SetTexCoords = [&](float u, float v, GSVertex& vtx_out) {
if constexpr (fst)
Expand All @@ -882,11 +883,15 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
vtx_out.XYZ.Y = xyof.y + static_cast<u32>(y * 16.0f);
};

const auto WriteQuad = [&](const GSVector4& xy, GSVector4 uv, GSVertex*& vout, u16*& iout) {
const auto WriteQuad = [&](const GSVector4i& xyi, const GSVector4i& uvi, GSVertex*& vout, u16*& iout) {
GSVector4 xy(xyi);
GSVector4 uv(uvi);

if (bilinear)
{
// Translate to texel center for bilinear.
uv += GSVector4(0.5f);
GL_INS("Translate to texel center for bilinear.");
uv += GSVector4(0.5f) / rt->GetScale();
}

if constexpr (primclass == GS_SPRITE_CLASS)
Expand Down Expand Up @@ -994,6 +999,7 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G

if (m_texture_shuffle.real_16_bit_source)
{
GL_INS("Real 16 bit source: no tex coord change.");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a minor nitpick, can you add HW: prefix to the logs? The rest as well.

half_u = false;
half_v = false;
}
Expand All @@ -1002,6 +1008,7 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
m_texture_shuffle.type == TextureShuffleType::TwoPixel ||
m_texture_shuffle.type == TextureShuffleType::HackShuffle)
{
GL_INS("Split shuffle/TwoPixel/HackShuffle: no pos or tex coord change.");
half_x = false;
half_y = false;
half_u = false;
Expand All @@ -1012,6 +1019,8 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
// Currently, this shuffle is done with the NFS CRC hack.
// It is a split texture shuffle, but the draws are skipped with the hack instead of
// being combined in the usual way, so we need to adjust the draw rect here.
GL_INS("GappedSwizzle (NFS Undercover): rewriting rects to use full area.");

half_x = false;
half_y = false;
half_u = false;
Expand All @@ -1020,12 +1029,12 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
m_r = rt->GetUnscaledRect();
tex_r = tex->GetUnscaledRect();
scissor_r = m_r;

GL_INS("GappedSwizzle (NFS Undercover): rewriting rects to use full area.");
}
else if (m_texture_shuffle.type == TextureShuffleType::Swizzle ||
m_texture_shuffle.type == TextureShuffleType::SwizzleTex32)
{
GL_INS("Swizzle/SwizzleTex32: no tex coord change.");

if (m_cached_ctx.FRAME.FBW == rt->m_TEX0.TBW * 2)
{
half_y = false;
Expand All @@ -1044,6 +1053,7 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
// No super source of truth here, since the width can get batted around, the valid is probably our best bet.
// Dogs will reuse the Z in a different size format for a completely unrelated draw with an FBW of 2,
// then go back to using it in full width.
GL_INS("Non-recursive draw, complex case.");

const bool tex_tbw_is_wrong =
tex->m_target &&
Expand Down Expand Up @@ -1131,6 +1141,7 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
else
{
// Handle recursive draws.
GL_INS("Recursive draw, complex case.");

const GSVector2i& frame_pgs = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM].pgs;

Expand Down Expand Up @@ -1227,7 +1238,7 @@ void GSRendererHW::ConvertSpriteTextureShuffleImpl(GSTextureCache::Target* rt, G
GSVertex* vout = m_vertex.buff;
u16* iout = m_index.buff;

WriteQuad(GSVector4(m_r), GSVector4(tex_r), vout, iout);
WriteQuad(m_r, tex_r, vout, iout);

m_index.tail = iout - m_index.buff;
m_vertex.head = m_vertex.tail = m_vertex.next = vout - m_vertex.buff;
Expand Down Expand Up @@ -1267,7 +1278,8 @@ GSVector4 GSRendererHW::RealignTargetTextureCoordinate(const GSTextureCache::Sou
{
if (GSConfig.UserHacks_HalfPixelOffset <= GSHalfPixelOffset::Normal ||
GSConfig.UserHacks_HalfPixelOffset >= GSHalfPixelOffset::Native ||
GetUpscaleMultiplier() == 1.0f || m_downscale_source || tex->GetScale() == 1.0f)
GetUpscaleMultiplier() == 1.0f || m_downscale_source || tex->GetScale() == 1.0f ||
m_texture_shuffle) // Do not apply HPO on texture shuffles as it already aligns the coordinates.
{
return GSVector4(0.0f);
}
Expand Down Expand Up @@ -5359,7 +5371,9 @@ void GSRendererHW::SetupIA(float target_scale, float sx, float sy, bool req_vert
{
GL_PUSH("HW: IA");

if (GSConfig.UserHacks_ForceEvenSpritePosition && !m_isPackedUV_HackFlag && m_process_texture && PRIM->FST)
// Do not force even sprite positive for texture shuffles since the coordinates are already aligned.
if (GSConfig.UserHacks_ForceEvenSpritePosition && !m_isPackedUV_HackFlag && m_process_texture && PRIM->FST &&
!m_texture_shuffle)
{
for (u32 i = 0; i < m_vertex.next; i++)
m_vertex.buff[i].UV &= 0x3FEF3FEF;
Expand Down Expand Up @@ -5986,7 +6000,8 @@ void GSRendererHW::DetermineVSConfig(GSTextureCache::Target* rt, float rtscale,
const float ox = static_cast<float>(static_cast<int>(m_context->XYOFFSET.OFX));
const float oy = static_cast<float>(static_cast<int>(m_context->XYOFFSET.OFY));

if ((GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native) && rtscale > 1.0f)
// Do not apply HPO on texture shuffle draws, as the coordinates are already aligned.
if ((GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native || m_texture_shuffle) && rtscale > 1.0f)
{
sx = 2.0f * rtscale / (rtsize.x << 4);
sy = 2.0f * rtscale / (rtsize.y << 4);
Expand Down Expand Up @@ -7520,7 +7535,8 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,

// Can be seen with the cabin part of the ship in God of War, offsets are required when using FST.
// ST uses a normalized position so doesn't need an offset here, will break Bionicle Heroes.
if (GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset)
// Do not apply HPO on texture shuffles as it already aligns the coordinates.
if (GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset && !m_texture_shuffle)
{
const u32 psm = rt ? rt->m_TEX0.PSM : ds->m_TEX0.PSM;
const bool can_offset = m_r.width() > GSLocalMemory::m_psm[psm].pgs.x || m_r.height() > GSLocalMemory::m_psm[psm].pgs.y;
Expand Down
Loading