Skip to content

Commit b429b4e

Browse files
committed
Add option for dump every mod B frames/draws.
1 parent b171d2a commit b429b4e

File tree

7 files changed

+74
-69
lines changed

7 files changed

+74
-69
lines changed

pcsx2-gsrunner/Main.cpp

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -445,10 +445,12 @@ static void PrintCommandLineHelp(const char* progname)
445445
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
446446
std::fprintf(stderr, " -dump [rt|tex|z|f|a]: Enabling dunmping of render target, texture, z buffer, frame, "
447447
"and alphas (respectively) per draw. Always enables dumping context/vertices. Generates lots of data.\n");
448-
std::fprintf(stderr, " -dumprange N[,L]: Start dumping from draw N (base 0) and stops after L draws (smaller of -dumprange and -dumrangef used)."
449-
"Defaults to N=0 and L=-1 (all draws). Only used if -dump used.\n");
450-
std::fprintf(stderr, " -dumprangef NF[,LF]: Start dumping from frame NF (base 0) and stops after LF frames (smaller of -dumprange and -dumrangef used).\n"
451-
"Defaults to NF=0 and LF=-1 (all frames). Only used if -dump is used.\n");
448+
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
449+
"those draws that are multiples of B (intersection of -dumprange and -dumrangef used)."
450+
"Defaults to N=0,L=-1,B=1 (all draws). Only used if -dump used.\n");
451+
std::fprintf(stderr, " -dumprangef NF[,LF,BF]: Start dumping from frame NF (base 0), stops after LF frames, "
452+
"and only those frames that are multiples of BF (intersection of -dumprange and -dumrangef used).\n"
453+
"Defaults to NF=0,LF=-1,BF=1 (all frames). Only used if -dump is used.\n");
452454
std::fprintf(stderr, " -loop <count>: Loops dump playback N times. Defaults to 1. 0 will loop infinitely.\n");
453455
std::fprintf(stderr, " -renderer <renderer>: Sets the graphics renderer. Defaults to Auto.\n");
454456
std::fprintf(stderr, " -window: Forces a window to be displayed.\n");
@@ -514,8 +516,10 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
514516
s_settings_interface.SetBoolValue("EmuCore/GS", "dump", true);
515517
s_settings_interface.SetIntValue("EmuCore/GS", "saven", 0);
516518
s_settings_interface.SetIntValue("EmuCore/GS", "savel", -1);
519+
s_settings_interface.SetIntValue("EmuCore/GS", "saveb", 1);
517520
s_settings_interface.SetIntValue("EmuCore/GS", "savenf", 0);
518521
s_settings_interface.SetIntValue("EmuCore/GS", "savelf", -1);
522+
s_settings_interface.SetIntValue("EmuCore/GS", "savelf", 1);
519523

520524
if (str.find("rt") != std::string::npos)
521525
s_settings_interface.SetBoolValue("EmuCore/GS", "save", true);
@@ -536,6 +540,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
536540
std::vector<std::string_view> split = StringUtil::SplitString(str, ',');
537541
int start = 0;
538542
int num = -1;
543+
int by = 1;
539544
if (split.size() > 0)
540545
{
541546
start = StringUtil::FromChars<int>(split[0]).value_or(0);
@@ -544,8 +549,13 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
544549
{
545550
num = StringUtil::FromChars<int>(split[1]).value_or(-1);
546551
}
552+
if (split.size() > 2)
553+
{
554+
by = std::max(1, StringUtil::FromChars<int>(split[2]).value_or(1));
555+
}
547556
s_settings_interface.SetIntValue("EmuCore/GS", "saven", start);
548557
s_settings_interface.SetIntValue("EmuCore/GS", "savel", num);
558+
s_settings_interface.SetIntValue("EmuCore/GS", "saveb", by);
549559
continue;
550560
}
551561
else if (CHECK_ARG_PARAM("-dumprangef"))
@@ -555,6 +565,7 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
555565
std::vector<std::string_view> split = StringUtil::SplitString(str, ',');
556566
int start = 0;
557567
int num = -1;
568+
int by = 1;
558569
if (split.size() > 0)
559570
{
560571
start = StringUtil::FromChars<int>(split[0]).value_or(0);
@@ -563,8 +574,13 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
563574
{
564575
num = StringUtil::FromChars<int>(split[1]).value_or(-1);
565576
}
577+
if (split.size() > 2)
578+
{
579+
by = std::max(1, StringUtil::FromChars<int>(split[2]).value_or(1));
580+
}
566581
s_settings_interface.SetIntValue("EmuCore/GS", "savenf", start);
567582
s_settings_interface.SetIntValue("EmuCore/GS", "savelf", num);
583+
s_settings_interface.SetIntValue("EmuCore/GS", "savelb", by);
568584
continue;
569585
}
570586
else if (CHECK_ARG_PARAM("-dumpdirhw"))

pcsx2/Config.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -823,8 +823,10 @@ struct Pcsx2Config
823823

824824
int SaveN = 0;
825825
int SaveL = 5000;
826+
int SaveB = 1;
826827
int SaveNF = 0;
827828
int SaveLF = -1;
829+
int SaveBF = 1;
828830

829831
s8 ExclusiveFullscreenControl = -1;
830832
GSScreenshotSize ScreenshotSize = GSScreenshotSize::WindowResolution;
@@ -868,6 +870,9 @@ struct Pcsx2Config
868870

869871
bool operator==(const GSOptions& right) const;
870872
bool operator!=(const GSOptions& right) const;
873+
874+
// Should we dump this draw/frame?
875+
bool ShouldDump(int draw, int frame) const;
871876
};
872877

873878
struct SPU2Options

pcsx2/GS/GSState.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1994,7 +1994,7 @@ void GSState::InitReadFIFO(u8* mem, int len)
19941994
// Read the image all in one go.
19951995
m_mem.ReadImageX(m_tr.x, m_tr.y, m_tr.buff, m_tr.total, m_env.BITBLTBUF, m_env.TRXPOS, m_env.TRXREG);
19961996

1997-
if (GSConfig.DumpGSData && GSConfig.SaveRT && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
1997+
if (GSConfig.SaveRT && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
19981998
{
19991999
const std::string s(GetDrawDumpPath(
20002000
"%05d_read_%05x_%d_%d_%d_%d_%d_%d.bmp",

pcsx2/GS/Renderers/Common/GSRenderer.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -546,7 +546,7 @@ void GSRenderer::EndPresentFrame()
546546

547547
void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
548548
{
549-
if (GSConfig.DumpGSData && s_n >= GSConfig.SaveN)
549+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
550550
{
551551
DumpGSPrivRegs(*m_regs, GetDrawDumpPath("vsync_%05d_f%05lld_gs_reg.txt", s_n, g_perfmon.GetFrame()));
552552
}

pcsx2/GS/Renderers/HW/GSRendererHW.cpp

Lines changed: 8 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,7 @@ void GSRendererHW::RoundSpriteOffset()
19841984

19851985
void GSRendererHW::Draw()
19861986
{
1987-
if (GSConfig.DumpGSData && (s_n >= GSConfig.SaveN) && g_perfmon.GetFrame() >= GSConfig.SaveNF)
1987+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
19881988
{
19891989
std::string s;
19901990

@@ -3264,13 +3264,13 @@ void GSRendererHW::Draw()
32643264
src->m_texture = src->m_from_target->m_texture;
32653265
}
32663266

3267-
if (GSConfig.DumpGSData)
3267+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
32683268
{
32693269
const u64 frame = g_perfmon.GetFrame();
32703270

32713271
std::string s;
32723272

3273-
if (GSConfig.SaveTexture && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF && src)
3273+
if (GSConfig.SaveTexture && src)
32743274
{
32753275
s = GetDrawDumpPath("%05d_f%05lld_itex_%05x_%s_%d%d_%02x_%02x_%02x_%02x.dds",
32763276
s_n, frame, static_cast<int>(m_cached_ctx.TEX0.TBP0), psm_str(m_cached_ctx.TEX0.PSM),
@@ -3288,15 +3288,15 @@ void GSRendererHW::Draw()
32883288
}
32893289
}
32903290

3291-
if (rt && GSConfig.SaveRT && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
3291+
if (rt && GSConfig.SaveRT)
32923292
{
32933293
s = GetDrawDumpPath("%05d_f%05lld_rt0_%05x_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), psm_str(m_cached_ctx.FRAME.PSM));
32943294

32953295
if (rt->m_texture)
32963296
rt->m_texture->Save(s);
32973297
}
32983298

3299-
if (ds && GSConfig.SaveDepth && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
3299+
if (ds && GSConfig.SaveDepth)
33003300
{
33013301
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), psm_str(m_cached_ctx.ZBUF.PSM));
33023302

@@ -3415,31 +3415,25 @@ void GSRendererHW::Draw()
34153415

34163416
//
34173417

3418-
if (GSConfig.DumpGSData)
3418+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
34193419
{
34203420
const u64 frame = g_perfmon.GetFrame();
34213421

34223422
std::string s;
34233423

3424-
if (GSConfig.SaveRT && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
3424+
if (GSConfig.SaveRT)
34253425
{
34263426
s = GetDrawDumpPath("%05d_f%05lld_rt1_%05x_%s.bmp", s_n, frame, m_cached_ctx.FRAME.Block(), psm_str(m_cached_ctx.FRAME.PSM));
34273427

34283428
rt->m_texture->Save(s);
34293429
}
34303430

3431-
if (GSConfig.SaveDepth && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
3431+
if (GSConfig.SaveDepth)
34323432
{
34333433
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_cached_ctx.ZBUF.Block(), psm_str(m_cached_ctx.ZBUF.PSM));
34343434

34353435
ds->m_texture->Save(s);
34363436
}
3437-
3438-
if ((GSConfig.SaveL > 0 && (s_n - GSConfig.SaveN) >= GSConfig.SaveL) ||
3439-
(GSConfig.SaveLF > 0 && ((int)g_perfmon.GetFrame() - GSConfig.SaveNF) >= GSConfig.SaveLF))
3440-
{
3441-
GSConfig.DumpGSData = 0;
3442-
}
34433437
}
34443438

34453439
if (rt)

pcsx2/GS/Renderers/SW/GSRendererSW.cpp

Lines changed: 26 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -179,12 +179,9 @@ GSTexture* GSRendererSW::GetOutput(int i, float& scale, int& y_offset)
179179

180180
m_texture[index]->Update(out_r, m_output, pitch);
181181

182-
if (GSConfig.DumpGSData)
182+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()) && GSConfig.SaveFrame)
183183
{
184-
if (GSConfig.SaveFrame && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
185-
{
186-
m_texture[index]->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), psm_str(curFramebuffer.PSM)));
187-
}
184+
m_texture[index]->Save(GetDrawDumpPath("%05d_f%05lld_fr%d_%05x_%s.bmp", s_n, g_perfmon.GetFrame(), i, (int)curFramebuffer.Block(), psm_str(curFramebuffer.PSM)));
188185
}
189186
}
190187

@@ -312,22 +309,17 @@ void GSRendererSW::Draw()
312309
{
313310
const GSDrawingContext* context = m_context;
314311

315-
if (GSConfig.DumpGSData)
312+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
316313
{
317-
std::string s;
314+
// Dump Register state
315+
std::string s = GetDrawDumpPath("%05d_context.txt", s_n);
318316

319-
if (s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
320-
{
321-
// Dump Register state
322-
s = GetDrawDumpPath("%05d_context.txt", s_n);
323-
324-
m_draw_env->Dump(s);
325-
m_context->Dump(s);
317+
m_draw_env->Dump(s);
318+
m_context->Dump(s);
326319

327-
// Dump vertices
328-
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
329-
DumpVertices(s);
330-
}
320+
// Dump vertices
321+
s = GetDrawDumpPath("%05d_vertex.txt", s_n);
322+
DumpVertices(s);
331323
}
332324

333325
auto data = m_vertex_heap.make_shared<SharedData>().cast<GSRasterizerData>();
@@ -431,9 +423,7 @@ void GSRendererSW::Draw()
431423

432424
sd->UsePages(fb_pages, m_context->offset.fb.psm(), zb_pages, m_context->offset.zb.psm());
433425

434-
//
435-
436-
if (GSConfig.DumpGSData)
426+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
437427
{
438428
Sync(2);
439429

@@ -444,7 +434,7 @@ void GSRendererSW::Draw()
444434
// It will breaks the few games that really uses 16 bits RT
445435
bool texture_shuffle = ((context->FRAME.PSM & 0x2) && ((context->TEX0.PSM & 3) == 2) && (m_vt.m_primclass == GS_SPRITE_CLASS));
446436

447-
if (GSConfig.SaveTexture && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF && PRIM->TME)
437+
if (GSConfig.SaveTexture && PRIM->TME)
448438
{
449439
if (texture_shuffle)
450440
{
@@ -457,7 +447,7 @@ void GSRendererSW::Draw()
457447
m_mem.SaveBMP(s, m_context->TEX0.TBP0, m_context->TEX0.TBW, m_context->TEX0.PSM, 1 << m_context->TEX0.TW, 1 << m_context->TEX0.TH);
458448
}
459449

460-
if (GSConfig.SaveRT && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
450+
if (GSConfig.SaveRT)
461451
{
462452

463453
if (texture_shuffle)
@@ -471,7 +461,7 @@ void GSRendererSW::Draw()
471461
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
472462
}
473463

474-
if (GSConfig.SaveDepth && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
464+
if (GSConfig.SaveDepth)
475465
{
476466
s = GetDrawDumpPath("%05d_f%05lld_rz0_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), psm_str(m_context->ZBUF.PSM));
477467

@@ -482,7 +472,7 @@ void GSRendererSW::Draw()
482472

483473
Sync(3);
484474

485-
if (GSConfig.SaveRT && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
475+
if (GSConfig.SaveRT)
486476
{
487477
if (texture_shuffle)
488478
{
@@ -495,18 +485,12 @@ void GSRendererSW::Draw()
495485
m_mem.SaveBMP(s, m_context->FRAME.Block(), m_context->FRAME.FBW, m_context->FRAME.PSM, r.z, r.w);
496486
}
497487

498-
if (GSConfig.SaveDepth && s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
488+
if (GSConfig.SaveDepth)
499489
{
500490
s = GetDrawDumpPath("%05d_f%05lld_rz1_%05x_%s.bmp", s_n, frame, m_context->ZBUF.Block(), psm_str(m_context->ZBUF.PSM));
501491

502492
m_mem.SaveBMP(s, m_context->ZBUF.Block(), m_context->FRAME.FBW, m_context->ZBUF.PSM, r.z, r.w);
503493
}
504-
505-
if ((GSConfig.SaveL > 0 && (s_n - GSConfig.SaveN) >= GSConfig.SaveL) ||
506-
(GSConfig.SaveLF > 0 && ((int)g_perfmon.GetFrame() - GSConfig.SaveNF) >= GSConfig.SaveLF))
507-
{
508-
GSConfig.DumpGSData = 0;
509-
}
510494
}
511495
else
512496
{
@@ -1547,28 +1531,21 @@ void GSRendererSW::SharedData::UpdateSource()
15471531
}
15481532
}
15491533

1550-
if (GSConfig.DumpGSData)
1534+
if (GSConfig.SaveTexture && GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
15511535
{
1552-
const u64 frame = g_perfmon.GetFrame();
1553-
1554-
std::string s;
1555-
1556-
if (GSConfig.SaveTexture && g_gs_renderer->s_n >= GSConfig.SaveN && g_perfmon.GetFrame() >= GSConfig.SaveNF)
1536+
for (size_t i = 0; m_tex[i].t; i++)
15571537
{
1558-
for (size_t i = 0; m_tex[i].t; i++)
1559-
{
1560-
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
1538+
const GIFRegTEX0& TEX0 = g_gs_renderer->GetTex0Layer(i);
15611539

1562-
s = GetDrawDumpPath("%05d_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, frame, i, TEX0.TBP0, psm_str(TEX0.PSM));
1540+
std::string s = GetDrawDumpPath("%05d_f%05lld_itex%d_%05x_%s.bmp", g_gs_renderer->s_n, g_perfmon.GetFrame(), i, TEX0.TBP0, psm_str(TEX0.PSM));
15631541

1564-
m_tex[i].t->Save(s);
1565-
}
1542+
m_tex[i].t->Save(s);
1543+
}
15661544

1567-
if (global.clut)
1568-
{
1569-
s = GetDrawDumpPath("%05d_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, frame, (int)g_gs_renderer->m_context->TEX0.CBP, psm_str(g_gs_renderer->m_context->TEX0.CPSM));
1570-
GSPng::Save((IsDevBuild || GSConfig.SaveAlpha) ? GSPng::RGB_A_PNG : GSPng::RGB_PNG, s, reinterpret_cast<const u8*>(global.clut), 256, 1, sizeof(u32) * 256, GSConfig.PNGCompressionLevel, false);
1571-
}
1545+
if (global.clut)
1546+
{
1547+
std::string s = GetDrawDumpPath("%05d_f%05lld_itexp_%05x_%s.bmp", g_gs_renderer->s_n, g_perfmon.GetFrame(), (int)g_gs_renderer->m_context->TEX0.CBP, psm_str(g_gs_renderer->m_context->TEX0.CPSM));
1548+
GSPng::Save((IsDevBuild || GSConfig.SaveAlpha) ? GSPng::RGB_A_PNG : GSPng::RGB_PNG, s, reinterpret_cast<const u8*>(global.clut), 256, 1, sizeof(u32) * 256, GSConfig.PNGCompressionLevel, false);
15721549
}
15731550
}
15741551
}

pcsx2/Pcsx2Config.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -840,6 +840,10 @@ bool Pcsx2Config::GSOptions::OptionsAreEqual(const GSOptions& right) const
840840
OpEqu(PNGCompressionLevel) &&
841841
OpEqu(SaveN) &&
842842
OpEqu(SaveL) &&
843+
OpEqu(SaveB) &&
844+
OpEqu(SaveNF) &&
845+
OpEqu(SaveLF) &&
846+
OpEqu(SaveBF) &&
843847

844848
OpEqu(ExclusiveFullscreenControl) &&
845849
OpEqu(ScreenshotSize) &&
@@ -1027,8 +1031,10 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
10271031
SettingsWrapBitfieldEx(PNGCompressionLevel, "png_compression_level");
10281032
SettingsWrapBitfieldEx(SaveN, "saven");
10291033
SettingsWrapBitfieldEx(SaveL, "savel");
1034+
SettingsWrapBitfieldEx(SaveL, "saveb");
10301035
SettingsWrapBitfieldEx(SaveNF, "savenf");
10311036
SettingsWrapBitfieldEx(SaveLF, "savelf");
1037+
SettingsWrapBitfieldEx(SaveLF, "savebf");
10321038

10331039
SettingsWrapEntryEx(CaptureContainer, "CaptureContainer");
10341040
SettingsWrapEntryEx(VideoCaptureCodec, "VideoCaptureCodec");
@@ -1113,6 +1119,13 @@ bool Pcsx2Config::GSOptions::UseHardwareRenderer() const
11131119
return (Renderer != GSRendererType::Null && Renderer != GSRendererType::SW);
11141120
}
11151121

1122+
bool Pcsx2Config::GSOptions::ShouldDump(int draw, int frame) const
1123+
{
1124+
return DumpGSData &&
1125+
(SaveN <= draw) && (draw < SaveN + SaveL) && (draw % SaveB == 0) &&
1126+
(SaveNF <= frame) && (frame < SaveNF + SaveLF) && (frame % SaveBF == 0);
1127+
}
1128+
11161129
static constexpr const std::array s_spu2_sync_mode_names = {
11171130
"Disabled",
11181131
"TimeStretch",

0 commit comments

Comments
 (0)