mirror of https://github.com/PCSX2/pcsx2.git
GS: Pre-round/truncate STQ values based on hardware tests
This commit is contained in:
parent
a60c30155e
commit
2fd24277c1
|
@ -27,6 +27,7 @@
|
|||
#include <cfloat>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <bit>
|
||||
|
||||
int GSState::s_n = 0;
|
||||
int GSState::s_last_transfer_draw_n = 0;
|
||||
|
@ -503,7 +504,7 @@ void GSState::DumpVertices(const std::string& filename)
|
|||
file << uv_U << DEL << uv_V;
|
||||
}
|
||||
else
|
||||
file << v.ST.S << DEL << v.ST.T << DEL << v.RGBAQ.Q;
|
||||
file << v.ST.S << "(" << std::bit_cast<u32>(v.ST.S) << ")" << DEL << v.ST.T << "(" << std::bit_cast<u32>(v.ST.T) << ")" << DEL << v.RGBAQ.Q << "(" << std::bit_cast<u32>(v.RGBAQ.Q) << ")";
|
||||
|
||||
file << std::endl;
|
||||
}
|
||||
|
@ -1593,6 +1594,13 @@ inline bool GSState::TestDrawChanged()
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 GSState::CalcMask(int exp, int max_exp)
|
||||
{
|
||||
const int amount = 9 + (max_exp - exp);
|
||||
|
||||
return (1 << std::min(amount, 23)) - 1;
|
||||
}
|
||||
|
||||
void GSState::FlushPrim()
|
||||
{
|
||||
if (m_index.tail > 0)
|
||||
|
@ -1668,6 +1676,50 @@ 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 (m_env.PRIM.TME && (GSUtil::GetPrimClass(PRIM->PRIM) == GS_PRIM_CLASS::GS_SPRITE_CLASS || m_vt.m_eq.z))
|
||||
{
|
||||
if (!m_env.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<int>(v->ST.T);
|
||||
int Q = std::bit_cast<int>(v->RGBAQ.Q);
|
||||
int S = std::bit_cast<int>(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<float>(S);
|
||||
max_exp = std::max(expT, expQ);
|
||||
mask = CalcMask(expT, max_exp);
|
||||
T &= ~mask;
|
||||
v->ST.T = std::bit_cast<float>(T);
|
||||
Q &= ~0xff;
|
||||
|
||||
if (!is_sprite || (i & 1))
|
||||
v->RGBAQ.Q = std::bit_cast<float>(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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 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);
|
||||
|
||||
|
|
|
@ -383,6 +383,7 @@ public:
|
|||
virtual void UpdateSettings(const Pcsx2Config::GSOptions& old_config);
|
||||
|
||||
void Flush(GSFlushReason reason);
|
||||
u32 CalcMask(int exp, int max_exp);
|
||||
void FlushPrim();
|
||||
bool TestDrawChanged();
|
||||
void FlushWrite();
|
||||
|
|
Loading…
Reference in New Issue