gsdx: dump and log EE texture read

It gives a visual opportunity to detect a bad read of the texture cache
This commit is contained in:
Gregory Hainaut 2016-07-14 19:41:21 +02:00
parent d855bc5ca8
commit 25bc2dff07
4 changed files with 38 additions and 24 deletions

View File

@ -53,6 +53,7 @@ GSRendererHW::GSRendererHW(GSTextureCache* tc)
m_userhacks_align_sprite_X = 0; m_userhacks_align_sprite_X = 0;
} }
m_dump_root = root_hw;
} }
void GSRendererHW::SetScaling() void GSRendererHW::SetScaling()
@ -217,7 +218,7 @@ GSTexture* GSRendererHW::GetOutput(int i, int& y_offset)
{ {
if(s_savef && s_n >= s_saven) if(s_savef && s_n >= s_saven)
{ {
t->Save(root_hw + format("%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM)); t->Save(m_dump_root + format("%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)TEX0.TBP0, (int)TEX0.PSM));
} }
} }
@ -517,8 +518,8 @@ void GSRendererHW::Draw()
// Dump Register state // Dump Register state
s = format("%05d_context.txt", s_n); s = format("%05d_context.txt", s_n);
m_env.Dump(root_hw+s); m_env.Dump(m_dump_root+s);
m_context->Dump(root_hw+s); m_context->Dump(m_dump_root+s);
} }
if(s_savet && s_n >= s_saven && tex) if(s_savet && s_n >= s_saven && tex)
@ -529,13 +530,13 @@ void GSRendererHW::Draw()
(int)context->CLAMP.MINU, (int)context->CLAMP.MAXU, (int)context->CLAMP.MINU, (int)context->CLAMP.MAXU,
(int)context->CLAMP.MINV, (int)context->CLAMP.MAXV); (int)context->CLAMP.MINV, (int)context->CLAMP.MAXV);
tex->m_texture->Save(root_hw+s, false, true); tex->m_texture->Save(m_dump_root+s, false, true);
if(tex->m_palette) if(tex->m_palette)
{ {
s = format("%05d_f%lld_tpx_%05x_%d.dds", s_n, frame, context->TEX0.CBP, context->TEX0.CPSM); s = format("%05d_f%lld_tpx_%05x_%d.dds", s_n, frame, context->TEX0.CBP, context->TEX0.CPSM);
tex->m_palette->Save(root_hw+s, false, true); tex->m_palette->Save(m_dump_root+s, false, true);
} }
} }
@ -546,7 +547,7 @@ void GSRendererHW::Draw()
s = format("%05d_f%lld_rt0_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM); s = format("%05d_f%lld_rt0_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM);
if (rt) if (rt)
rt->m_texture->Save(root_hw+s); rt->m_texture->Save(m_dump_root+s);
} }
if(s_savez && s_n >= s_saven) if(s_savez && s_n >= s_saven)
@ -554,7 +555,7 @@ void GSRendererHW::Draw()
s = format("%05d_f%lld_rz0_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM); s = format("%05d_f%lld_rz0_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM);
if (ds_tex) if (ds_tex)
ds_tex->Save(root_hw+s); ds_tex->Save(m_dump_root+s);
} }
s_n++; s_n++;
@ -706,7 +707,7 @@ void GSRendererHW::Draw()
s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM); s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, frame, context->FRAME.Block(), context->FRAME.PSM);
if (rt) if (rt)
rt->m_texture->Save(root_hw+s); rt->m_texture->Save(m_dump_root+s);
} }
if(s_savez && s_n >= s_saven) if(s_savez && s_n >= s_saven)
@ -714,7 +715,7 @@ void GSRendererHW::Draw()
s = format("%05d_f%lld_rz1_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM); s = format("%05d_f%lld_rz1_%05x_%d.bmp", s_n, frame, context->ZBUF.Block(), context->ZBUF.PSM);
if (ds_tex) if (ds_tex)
ds_tex->Save(root_hw+s); ds_tex->Save(m_dump_root+s);
} }
s_n++; s_n++;

View File

@ -62,6 +62,8 @@ GSRendererSW::GSRendererSW(int threads)
InitCVB(GS_LINE_CLASS); InitCVB(GS_LINE_CLASS);
InitCVB(GS_TRIANGLE_CLASS); InitCVB(GS_TRIANGLE_CLASS);
InitCVB(GS_SPRITE_CLASS); InitCVB(GS_SPRITE_CLASS);
m_dump_root = root_sw;
} }
GSRendererSW::~GSRendererSW() GSRendererSW::~GSRendererSW()
@ -258,7 +260,7 @@ GSTexture* GSRendererSW::GetOutput(int i, int& y_offset)
{ {
if(s_savef && s_n >= s_saven) if(s_savef && s_n >= s_saven)
{ {
m_texture[i]->Save(root_sw + format("%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM)); m_texture[i]->Save(m_dump_root + format("%05d_f%lld_fr%d_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), i, (int)DISPFB.Block(), (int)DISPFB.PSM));
} }
s_n++; s_n++;
@ -531,8 +533,8 @@ void GSRendererSW::Draw()
// Dump Register state // Dump Register state
s = format("%05d_context.txt", s_n); s = format("%05d_context.txt", s_n);
m_env.Dump(root_sw+s); m_env.Dump(m_dump_root+s);
m_context->Dump(root_sw+s); m_context->Dump(m_dump_root+s);
} }
if(s_savet && s_n >= s_saven && PRIM->TME) if(s_savet && s_n >= s_saven && PRIM->TME)
@ -540,11 +542,11 @@ void GSRendererSW::Draw()
if (texture_shuffle) { if (texture_shuffle) {
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect // Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = format("%05d_f%lld_tex_%05x_32bits.bmp", s_n, frame, (int)m_context->TEX0.TBP0); s = format("%05d_f%lld_tex_%05x_32bits.bmp", s_n, frame, (int)m_context->TEX0.TBP0);
m_mem.SaveBMP(root_sw+s, m_context->TEX0.TBP0, m_context->TEX0.TBW, 0, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH); m_mem.SaveBMP(m_dump_root+s, m_context->TEX0.TBP0, m_context->TEX0.TBW, 0, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
} }
s = format("%05d_f%lld_tex_%05x_%d.bmp", s_n, frame, (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM); s = format("%05d_f%lld_tex_%05x_%d.bmp", s_n, frame, (int)m_context->TEX0.TBP0, (int)m_context->TEX0.PSM);
m_mem.SaveBMP(root_sw+s, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH); m_mem.SaveBMP(m_dump_root+s, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
} }
s_n++; s_n++;
@ -555,18 +557,18 @@ void GSRendererSW::Draw()
if (texture_shuffle) { if (texture_shuffle) {
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect // Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = format("%05d_f%lld_rt0_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block()); s = format("%05d_f%lld_rt0_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
m_mem.SaveBMP(root_sw+s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, GetFrameRect().width(), 512);
} }
s = format("%05d_f%lld_rt0_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM); s = format("%05d_f%lld_rt0_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM);
m_mem.SaveBMP(root_sw+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512);
} }
if(s_savez && s_n >= s_saven) if(s_savez && s_n >= s_saven)
{ {
s = format("%05d_f%lld_rz0_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM); s = format("%05d_f%lld_rz0_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM);
m_mem.SaveBMP(root_sw+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512);
} }
s_n++; s_n++;
@ -580,18 +582,18 @@ void GSRendererSW::Draw()
if (texture_shuffle) { if (texture_shuffle) {
// Dump the RT in 32 bits format. It helps to debug texture shuffle effect // Dump the RT in 32 bits format. It helps to debug texture shuffle effect
s = format("%05d_f%lld_rt1_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block()); s = format("%05d_f%lld_rt1_%05x_32bits.bmp", s_n, frame, m_context->FRAME.Block());
m_mem.SaveBMP(root_sw+s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->FRAME.Block(), m_context->FRAME.FBW, 0, GetFrameRect().width(), 512);
} }
s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM); s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, frame, m_context->FRAME.Block(), m_context->FRAME.PSM);
m_mem.SaveBMP(root_sw+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512);
} }
if(s_savez && s_n >= s_saven) if(s_savez && s_n >= s_saven)
{ {
s = format("%05d_f%lld_rz1_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM); s = format("%05d_f%lld_rz1_%05x_%d.bmp", s_n, frame, m_context->ZBUF.Block(), m_context->ZBUF.PSM);
m_mem.SaveBMP(root_sw+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512);
} }
s_n++; s_n++;
@ -685,14 +687,14 @@ void GSRendererSW::Sync(int reason)
{ {
s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM); s = format("%05d_f%lld_rt1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->FRAME.Block(), m_context->FRAME.PSM);
m_mem.SaveBMP(root_sw+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, GetFrameRect().width(), 512);
} }
if(s_savez) if(s_savez)
{ {
s = format("%05d_f%lld_zb1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->ZBUF.Block(), m_context->ZBUF.PSM); s = format("%05d_f%lld_zb1_%05x_%d.bmp", s_n, m_perfmon.GetFrame(), m_context->ZBUF.Block(), m_context->ZBUF.PSM);
m_mem.SaveBMP(root_sw+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512); m_mem.SaveBMP(m_dump_root+s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, GetFrameRect().width(), 512);
} }
} }

View File

@ -56,6 +56,7 @@ GSState::GSState()
s_savef = theApp.GetConfigB("savef"); s_savef = theApp.GetConfigB("savef");
s_saven = theApp.GetConfigI("saven"); s_saven = theApp.GetConfigI("saven");
s_savel = theApp.GetConfigI("savel"); s_savel = theApp.GetConfigI("savel");
m_dump_root = "";
#if defined(__unix__) #if defined(__unix__)
if (s_dump) { if (s_dump) {
GSmkdir("/tmp/GS_HW_dump"); GSmkdir("/tmp/GS_HW_dump");
@ -1663,8 +1664,10 @@ void GSState::Read(uint8* mem, int len)
int sy = m_env.TRXPOS.SSAY; int sy = m_env.TRXPOS.SSAY;
int w = m_env.TRXREG.RRW; int w = m_env.TRXREG.RRW;
int h = m_env.TRXREG.RRH; int h = m_env.TRXREG.RRH;
GSVector4i r(sx, sy, sx + w, sy + h);
// printf("Read len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d\n", len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h); GL_CACHE("Read! len=%d SBP=%05x SBW=%d SPSM=%d SSAX=%d SSAY=%d RRW=%d RRH=%d",
len, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM, sx, sy, w, h);
if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len)) if(!m_tr.Update(w, h, GSLocalMemory::m_psm[m_env.BITBLTBUF.SPSM].trbpp, len))
{ {
@ -1675,11 +1678,18 @@ void GSState::Read(uint8* mem, int len)
{ {
if(m_tr.x == sx && m_tr.y == sy) if(m_tr.x == sx && m_tr.y == sy)
{ {
InvalidateLocalMem(m_env.BITBLTBUF, GSVector4i(sx, sy, sx + w, sy + h)); InvalidateLocalMem(m_env.BITBLTBUF, r);
} }
} }
m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG); m_mem.ReadImageX(m_tr.x, m_tr.y, mem, len, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
if(s_dump && s_save && s_n >= s_saven) {
string s= m_dump_root + format("%05d_read_%05x_%d_%d_%d_%d_%d_%d.bmp",
s_n, (int)m_env.BITBLTBUF.SBP, (int)m_env.BITBLTBUF.SBW, (int)m_env.BITBLTBUF.SPSM,
r.left, r.top, r.right, r.bottom);
m_mem.SaveBMP(s, m_env.BITBLTBUF.SBP, m_env.BITBLTBUF.SBW, m_env.BITBLTBUF.SPSM, r.right, r.bottom);
}
} }
void GSState::Move() void GSState::Move()

View File

@ -229,6 +229,7 @@ public:
bool s_savef; bool s_savef;
int s_saven; int s_saven;
int s_savel; int s_savel;
string m_dump_root;
public: public:
GSState(); GSState();