diff --git a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp index ba7386100f13f..4371022a30313 100644 --- a/pcsx2/GS/Renderers/HW/GSRendererHW.cpp +++ b/pcsx2/GS/Renderers/HW/GSRendererHW.cpp @@ -4377,10 +4377,13 @@ __ri void GSRendererHW::EmulateTextureSampler(const GSTextureCache::Target* rt, if (complex_wms_wmt) { // Add 0.5 to the coordinates because the region clamp is inclusive, size is exclusive. We use 0.5 because we want to clamp - // to the last texel in the image, not halfway between it and wrapping around. + // to the last texel in the image, not halfway between it and wrapping around. We *should* be doing this when upscaling, + // but having it off-by-one masks some draw issues in VP2 and Xenosaga. TODO: Fix the underlying draw issues. const GSVector4i clamp(m_cached_ctx.CLAMP.MINU, m_cached_ctx.CLAMP.MINV, m_cached_ctx.CLAMP.MAXU, m_cached_ctx.CLAMP.MAXV); const GSVector4 region_repeat = GSVector4::cast(clamp); - const GSVector4 region_clamp = (GSVector4(clamp) + GSVector4::cxpr(0.0f, 0.0f, 0.5f, 0.5f)) / WH.xyxy(); + const GSVector4 region_clamp_offset = + (tex->GetScale() != 1.0f) ? GSVector4::cxpr(0.0f, 0.0f, 0.0f, 0.0f) : GSVector4::cxpr(0.0f, 0.0f, 0.5f, 0.5f); + const GSVector4 region_clamp = (GSVector4(clamp) + region_clamp_offset) / WH.xyxy(); if (wms >= CLAMP_REGION_CLAMP) { m_conf.cb_ps.MinMax.x = (wms == CLAMP_REGION_CLAMP && !m_conf.ps.depth_fmt) ? region_clamp.x : region_repeat.x;