From 8f552cf582c65dc452a9ace55114ebb693a53feb Mon Sep 17 00:00:00 2001 From: TJnotJT Date: Fri, 24 Jan 2025 13:22:24 -0500 Subject: [PATCH] temp-commit --- pcsx2-gsrunner/Main.cpp | 6 --- pcsx2/GS/GSState.cpp | 102 +++++++++++++++++++++++----------------- pcsx2/GS/GSState.h | 1 + 3 files changed, 60 insertions(+), 49 deletions(-) diff --git a/pcsx2-gsrunner/Main.cpp b/pcsx2-gsrunner/Main.cpp index 041e8e87ca5ed..07a50a2a76749 100644 --- a/pcsx2-gsrunner/Main.cpp +++ b/pcsx2-gsrunner/Main.cpp @@ -514,12 +514,6 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa std::string str(argv[++i]); s_settings_interface.SetBoolValue("EmuCore/GS", "dump", true); - s_settings_interface.SetIntValue("EmuCore/GS", "saven", 0); - s_settings_interface.SetIntValue("EmuCore/GS", "savel", -1); - s_settings_interface.SetIntValue("EmuCore/GS", "saveb", 1); - s_settings_interface.SetIntValue("EmuCore/GS", "savenf", 0); - s_settings_interface.SetIntValue("EmuCore/GS", "savelf", -1); - s_settings_interface.SetIntValue("EmuCore/GS", "savelf", 1); if (str.find("rt") != std::string::npos) s_settings_interface.SetBoolValue("EmuCore/GS", "save", true); diff --git a/pcsx2/GS/GSState.cpp b/pcsx2/GS/GSState.cpp index cd021d3bd0295..d1533acf4fc5b 100644 --- a/pcsx2/GS/GSState.cpp +++ b/pcsx2/GS/GSState.cpp @@ -1677,49 +1677,7 @@ void GSState::FlushPrim() m_vt.Update(m_vertex.buff, m_index.buff, m_vertex.tail, m_index.tail, GSUtil::GetPrimClass(PRIM->PRIM)); - // Texel coordinate rounding - // Helps Manhunt (lights shining through objects). - // Can help with some alignment issues when upscaling too, and is for both Software and Hardware renderers. - // Sometimes hardware doesn't get affected, likely due to the difference in how GPU's handle textures (Persona minimap). - if (PRIM->TME && (GSUtil::GetPrimClass(PRIM->PRIM) == GS_PRIM_CLASS::GS_SPRITE_CLASS || m_vt.m_eq.z)) - { - if (!PRIM->FST) // STQ's - { - const bool is_sprite = GSUtil::GetPrimClass(PRIM->PRIM) == GS_PRIM_CLASS::GS_SPRITE_CLASS; - // ST's have the lowest 9 bits (or greater depending on exponent difference) rounding down (from hardware tests). - for (int i = m_index.tail - 1; i >= 0; i--) - { - GSVertex* v = &m_vertex.buff[m_index.buff[i]]; - - // Only Q on the second vertex is valid - if (!(i & 1) && is_sprite) - v->RGBAQ.Q = m_vertex.buff[m_index.buff[i + 1]].RGBAQ.Q; - - int T = std::bit_cast(v->ST.T); - int Q = std::bit_cast(v->RGBAQ.Q); - int S = std::bit_cast(v->ST.S); - const int expS = (S >> 23) & 0xff; - const int expT = (T >> 23) & 0xff; - const int expQ = (Q >> 23) & 0xff; - int max_exp = std::max(expS, expQ); - - u32 mask = CalcMask(expS, max_exp); - S &= ~mask; - v->ST.S = std::bit_cast(S); - max_exp = std::max(expT, expQ); - mask = CalcMask(expT, max_exp); - T &= ~mask; - v->ST.T = std::bit_cast(T); - Q &= ~0xff; - - if (!is_sprite || (i & 1)) - v->RGBAQ.Q = std::bit_cast(Q); - - m_vt.m_min.t.x = std::min(m_vt.m_min.t.x, (v->ST.S / v->RGBAQ.Q) * (1 << m_context->TEX0.TW)); - m_vt.m_min.t.y = std::min(m_vt.m_min.t.y, (v->ST.T / v->RGBAQ.Q) * (1 << m_context->TEX0.TH)); - } - } - } + TexelCoordinateRounding(); // Skip draw if Z test is enabled, but set to fail all pixels. const bool skip_draw = (m_context->TEST.ZTE && m_context->TEST.ZTST == ZTST_NEVER); @@ -4009,6 +3967,64 @@ GSState::TextureMinMaxResult GSState::GetTextureMinMax(GIFRegTEX0 TEX0, GIFRegCL return { vr, uses_border }; } +// Texel coordinate rounding +// Helps Manhunt (lights shining through objects). +// Can help with some alignment issues when upscaling too, and is for both Software and Hardware renderers. +// Sometimes hardware doesn't get affected, likely due to the difference in how GPU's handle textures (Persona minimap). +void GSState::TexelCoordinateRounding() +{ + if (PRIM->TME && (GSUtil::GetPrimClass(PRIM->PRIM) == GS_PRIM_CLASS::GS_SPRITE_CLASS || m_vt.m_eq.z)) + { + if (!PRIM->FST) // STQ's + { + const bool is_sprite = GSUtil::GetPrimClass(PRIM->PRIM) == GS_PRIM_CLASS::GS_SPRITE_CLASS; + // ST's have the lowest 9 bits (or greater depending on exponent difference) rounding down (from hardware tests). + for (int i = m_index.tail - 1; i >= 0; i--) + { + GSVertex* v = &m_vertex.buff[m_index.buff[i]]; + + // Only Q on the second vertex is valid + if (!(i & 1) && is_sprite) + v->RGBAQ.Q = m_vertex.buff[m_index.buff[i + 1]].RGBAQ.Q; + + int T = std::bit_cast(v->ST.T); + int Q = std::bit_cast(v->RGBAQ.Q); + int S = std::bit_cast(v->ST.S); + const int expS = (S >> 23) & 0xff; + const int expT = (T >> 23) & 0xff; + const int expQ = (Q >> 23) & 0xff; + int max_exp = std::max(expS, expQ); + + u32 mask = CalcMask(expS, max_exp); + S &= ~mask; + v->ST.S = std::bit_cast(S); + max_exp = std::max(expT, expQ); + mask = CalcMask(expT, max_exp); + T &= ~mask; + v->ST.T = std::bit_cast(T); + Q &= ~0xff; + + if (!is_sprite || (i & 1)) + v->RGBAQ.Q = std::bit_cast(Q); + + float U = (v->ST.S / v->RGBAQ.Q) * (1 << m_context->TEX0.TW); + float V = (v->ST.T / v->RGBAQ.Q) * (1 << m_context->TEX0.TH); + + m_vt.m_min.t.x = std::isnan(U) ? m_vt.m_min.t.x : std::min(m_vt.m_min.t.x, U); + m_vt.m_min.t.y = std::isnan(V) ? m_vt.m_min.t.y : std::min(m_vt.m_min.t.y, V); + m_vt.m_max.t.x = std::isnan(U) ? m_vt.m_max.t.x : std::min(m_vt.m_max.t.x, U); + m_vt.m_max.t.y = std::isnan(V) ? m_vt.m_max.t.y : std::min(m_vt.m_max.t.y, V); + } + } + } + + // Clamp the min/max UV values to the min/max valid UV values. + // This is needed in certain cases where buggy GS input results + // in huge floating points values for ST. + m_vt.m_min.t = m_vt.m_min.t.min(GSVector4(2047.0f)).max(GSVector4(-2047.0f)).xyzw(m_vt.m_min.t); + m_vt.m_max.t = m_vt.m_max.t.min(GSVector4(2047.0f)).max(GSVector4(-2047.0f)).xyzw(m_vt.m_max.t); +} + void GSState::CalcAlphaMinMax(const int tex_alpha_min, const int tex_alpha_max) { if (m_vt.m_alpha.valid && tex_alpha_min == 0 && tex_alpha_max == 255) diff --git a/pcsx2/GS/GSState.h b/pcsx2/GS/GSState.h index 75416d86d5228..6d70bb5c7562d 100644 --- a/pcsx2/GS/GSState.h +++ b/pcsx2/GS/GSState.h @@ -190,6 +190,7 @@ class GSState : public GSAlignedClass<32> bool IsCoverageAlpha(); void CalcAlphaMinMax(const int tex_min, const int tex_max); void CorrectATEAlphaMinMax(const u32 atst, const int aref); + void TexelCoordinateRounding(); public: struct GSUploadQueue