Skip to content

Commit

Permalink
GS/HW: Add new HPO - Align to Native With Texture Offset
Browse files Browse the repository at this point in the history
  • Loading branch information
refractionpcsx2 committed Feb 23, 2025
1 parent 02789eb commit 74ed130
Show file tree
Hide file tree
Showing 5 changed files with 35 additions and 6 deletions.
5 changes: 5 additions & 0 deletions pcsx2-qt/Settings/GraphicsSettingsWidget.ui
Original file line number Diff line number Diff line change
Expand Up @@ -1058,6 +1058,11 @@
<string>Align To Native</string>
</property>
</item>
<item>
<property name="text">
<string> Align to Native - With Texture Offset</string>
</property>
</item>
</widget>
</item>
<item row="1" column="0">
Expand Down
1 change: 1 addition & 0 deletions pcsx2/Config.h
Original file line number Diff line number Diff line change
Expand Up @@ -440,6 +440,7 @@ enum class GSHalfPixelOffset : u8
Special,
SpecialAggressive,
Native,
NativeWTexOffset,
MaxCount
};

Expand Down
30 changes: 26 additions & 4 deletions pcsx2/GS/Renderers/HW/GSRendererHW.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5160,6 +5160,13 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,

const GSVector4 half_pixel = RealignTargetTextureCoordinate(tex);
m_conf.cb_vs.texture_offset = GSVector2(half_pixel.x, half_pixel.y);

if (tex->m_scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset)
{
m_conf.cb_vs.texture_offset.x += 7.0f + (0.5f * (tex->m_scale / 2));
m_conf.cb_vs.texture_offset.y += 7.0f + (0.5f * (tex->m_scale / 2));
}

}
else if (tex->m_target)
{
Expand Down Expand Up @@ -5211,6 +5218,12 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt,
const GSVector4 half_pixel = RealignTargetTextureCoordinate(tex);
m_conf.cb_vs.texture_offset = GSVector2(half_pixel.x, half_pixel.y);

if (PRIM->FST && tex->m_scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset)
{
m_conf.cb_vs.texture_offset.x += 4.0f + (0.5f * (tex->m_scale / 2));
m_conf.cb_vs.texture_offset.y += 4.0f + (0.5f * (tex->m_scale / 2));
}

if (m_vt.m_primclass == GS_SPRITE_CLASS && GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM].pal > 0 && m_index.tail >= 4)
{
HandleManualDeswizzle();
Expand Down Expand Up @@ -5540,7 +5553,7 @@ __ri void GSRendererHW::HandleTextureHazards(const GSTextureCache::Target* rt, c
// When using native HPO, the top-left column/row of pixels are often not drawn. Clamp these away to avoid sampling black,
// causing bleeding into the edges of the downsampled texture.
const u32 downsample_factor = static_cast<u32>(src_target->GetScale());
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native) ?
const GSVector2i clamp_min = (GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native) ?
GSVector2i(0, 0) :
GSVector2i(downsample_factor, downsample_factor);
GSVector4i copy_rect = tmm.coverage;
Expand Down Expand Up @@ -6272,7 +6285,8 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
float sx, sy, ox2, oy2;
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)

if ((GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native || m_channel_shuffle) && rtscale > 1.0f)
{
sx = 2.0f * rtscale / (rtsize.x << 4);
sy = 2.0f * rtscale / (rtsize.y << 4);
Expand Down Expand Up @@ -6301,8 +6315,16 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
const int unscaled_y = rt_or_ds ? rt_or_ds->GetUnscaledHeight() : 0;
sx = 2.0f / (unscaled_x << 4);
sy = 2.0f / (unscaled_y << 4);
ox2 = -1.0f / unscaled_x;
oy2 = -1.0f / unscaled_y;
if (GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::NativeWTexOffset)
{
ox2 = (-1.0f / unscaled_x) / rtscale;
oy2 = (-1.0f / unscaled_y) / rtscale;
}
else
{
ox2 = -1.0f / unscaled_x;
oy2 = -1.0f / unscaled_y;
}
}

m_conf.cb_vs.vertex_scale = GSVector2(sx, sy);
Expand Down
4 changes: 2 additions & 2 deletions pcsx2/GS/Renderers/HW/GSTextureCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2132,8 +2132,8 @@ GSTextureCache::Target* GSTextureCache::LookupTarget(GIFRegTEX0 TEX0, const GSVe
// And invalidate the target, we're drawing over it so we don't care what's there.
// We can't do this when upscaling, because of the vertex offset, the top/left rows often aren't drawn.
GL_INS("TC: Invalidating%s target %s[%x] because it's completely overwritten.", to_string(type),
(scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset == GSHalfPixelOffset::Native) ? "[clearing] " : "", dst->m_TEX0.TBP0);
if (scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset != GSHalfPixelOffset::Native)
(scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset >= GSHalfPixelOffset::Native) ? "[clearing] " : "", dst->m_TEX0.TBP0);
if (scale > 1.0f && GSConfig.UserHacks_HalfPixelOffset < GSHalfPixelOffset::Native)
{
if (dst->m_type == RenderTarget)
g_gs_device->ClearRenderTarget(dst->m_texture, 0);
Expand Down
1 change: 1 addition & 0 deletions pcsx2/ImGui/FullscreenUI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3810,6 +3810,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
FSUI_NSTR("Special (Texture)"),
FSUI_NSTR("Special (Texture - Aggressive)"),
FSUI_NSTR("Align To Native"),
FSUI_NSTR("Align to Native - With Texture Offset"),
};
static constexpr const char* s_native_scaling_options[] = {
FSUI_NSTR("Normal (Default)"),
Expand Down

0 comments on commit 74ed130

Please sign in to comment.