Skip to content

Commit f05905d

Browse files
committed
GS: Allow dumping draw/frames stats.
1 parent e550cf9 commit f05905d

File tree

12 files changed

+123
-3
lines changed

12 files changed

+123
-3
lines changed

pcsx2-gsrunner/Main.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,8 @@ static void PrintCommandLineHelp(const char* progname)
473473
std::fprintf(stderr, " -help: Displays this information and exits.\n");
474474
std::fprintf(stderr, " -version: Displays version information and exits.\n");
475475
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
476-
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr]: Enabling dumping of render target, texture, z buffer, frame, "
477-
"alphas, and info (context, vertices, transfers (list)), transfers (images), respectively, per draw. Generates lots of data.\n");
476+
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr|ds|fs]: Enabling dumping of render target, texture, z buffer, frame, "
477+
"alphas, and info (context, vertices, list of transfers), transfers images, draw stats, frame stats, respectively, per draw. Generates lots of data.\n");
478478
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
479479
"those draws that are multiples of B (intersection of -dumprange and -dumprangef used)."
480480
"Defaults to 0,-1,1 (all draws). Only used if -dump used.\n");
@@ -560,6 +560,10 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
560560
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveInfo", true);
561561
if (str.find("tr") != std::string::npos)
562562
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveTransferImages", true);
563+
if (str.find("ds") != std::string::npos)
564+
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveDrawStats", true);
565+
if (str.find("fs") != std::string::npos)
566+
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveFrameStats", true);
563567
continue;
564568
}
565569
else if (CHECK_ARG_PARAM("-dumprange"))

pcsx2-qt/Settings/DebugGSSettingsTab.ui

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,21 @@
7171
</property>
7272
</widget>
7373
</item>
74-
<item row="4" column="0">
74+
<item row="4" column="0">
75+
<widget class="QCheckBox" name="saveDrawStats">
76+
<property name="text">
77+
<string>Save Draw Stats</string>
78+
</property>
79+
</widget>
80+
</item>
81+
<item row="4" column="1">
82+
<widget class="QCheckBox" name="saveFrameStats">
83+
<property name="text">
84+
<string>Save Frame Stats</string>
85+
</property>
86+
</widget>
87+
</item>
88+
<item row="5" column="0">
7589
<widget class="QCheckBox" name="saveTransferImages">
7690
<property name="text">
7791
<string>Save Transfer Image Data</string>

pcsx2-qt/Settings/DebugSettingsWidget.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,8 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
110110
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveAlpha, "EmuCore/GS", "SaveAlpha", false);
111111
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveInfo, "EmuCore/GS", "SaveInfo", false);
112112
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveTransferImages, "EmuCore/GS", "SaveTransferImages", false);
113+
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveDrawStats, "EmuCore/GS", "SaveDrawStats", false);
114+
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveFrameStats, "EmuCore/GS", "SaveFrameStats", false);
113115
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawStart, "EmuCore/GS", "SaveDrawStart", 0);
114116
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawCount, "EmuCore/GS", "SaveDrawCount", 5000);
115117
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveFrameStart, "EmuCore/GS", "SaveFrameStart", 0);
@@ -215,6 +217,8 @@ void DebugSettingsWidget::onDrawDumpingChanged()
215217
m_gs.saveAlpha->setEnabled(enabled);
216218
m_gs.saveInfo->setEnabled(enabled);
217219
m_gs.saveTransferImages->setEnabled(enabled);
220+
m_gs.saveDrawStats->setEnabled(enabled);
221+
m_gs.saveFrameStats->setEnabled(enabled);
218222
m_gs.saveDrawStart->setEnabled(enabled);
219223
m_gs.saveDrawCount->setEnabled(enabled);
220224
m_gs.saveFrameStart->setEnabled(enabled);

pcsx2/Config.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -775,6 +775,8 @@ struct Pcsx2Config
775775
SaveAlpha : 1,
776776
SaveInfo : 1,
777777
SaveTransferImages : 1,
778+
SaveDrawStats : 1,
779+
SaveFrameStats : 1,
778780
DumpReplaceableTextures : 1,
779781
DumpReplaceableMipmaps : 1,
780782
DumpTexturesWithFMVActive : 1,

pcsx2/GS/GSPerfMon.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "GSPerfMon.h"
55
#include "GS.h"
6+
#include "GSUtil.h"
67

78
#include <cstring>
89

@@ -41,3 +42,27 @@ void GSPerfMon::Update()
4142

4243
memset(m_counters, 0, sizeof(m_counters));
4344
}
45+
46+
GSPerfMon GSPerfMon::operator-(const GSPerfMon& other)
47+
{
48+
GSPerfMon diff;
49+
for (std::size_t i = 0; i < std::size(diff.m_counters); i++)
50+
{
51+
diff.m_counters[i] = m_counters[i] - other.m_counters[i];
52+
}
53+
return diff;
54+
}
55+
56+
void GSPerfMon::Dump(const std::string& filename, bool hw)
57+
{
58+
FILE* fp = fopen(filename.c_str(), "w");
59+
if (!fp)
60+
return;
61+
62+
for (std::size_t i = 0; i < std::size(m_counters); i++)
63+
{
64+
fprintf(fp, "%s: %lu\n", GSUtil::GetPerfMonCounterName(static_cast<counter_t>(i), hw), static_cast<u64>(m_counters[i]));
65+
}
66+
67+
fclose(fp);
68+
}

pcsx2/GS/GSPerfMon.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include "common/Pcsx2Defs.h"
77

88
#include <ctime>
9+
#include <string>
910

1011
class GSPerfMon
1112
{
@@ -58,6 +59,10 @@ class GSPerfMon
5859
m_disp_fb_sprite_blits = 0;
5960
return blits;
6061
}
62+
63+
GSPerfMon operator-(const GSPerfMon& other);
64+
65+
void Dump(const std::string& filename, bool hw);
6166
};
6267

6368
extern GSPerfMon g_perfmon;

pcsx2/GS/GSState.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,9 @@ void GSState::Reset(bool hardware_reset)
202202
m_backed_up_ctx = -1;
203203

204204
memcpy(&m_prev_env, &m_env, sizeof(m_prev_env));
205+
206+
m_perfmon_draw.Reset();
207+
m_perfmon_frame.Reset();
205208
}
206209

207210
template<bool auto_flush>
@@ -2125,6 +2128,16 @@ void GSState::FlushPrim()
21252128
g_perfmon.Put(GSPerfMon::Draw, 1);
21262129
g_perfmon.Put(GSPerfMon::Prim, m_index.tail / GSUtil::GetVertexCount(PRIM->PRIM));
21272130

2131+
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
2132+
{
2133+
if (GSConfig.SaveDrawStats)
2134+
{
2135+
m_perfmon_draw = g_perfmon - m_perfmon_draw;
2136+
m_perfmon_draw.Dump(GetDrawDumpPath("%05d_draw_stats.txt", s_n), GSIsHardwareRenderer());
2137+
m_perfmon_draw = g_perfmon;
2138+
}
2139+
}
2140+
21282141
m_index.tail = 0;
21292142
m_vertex.head = 0;
21302143

pcsx2/GS/GSState.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#pragma once
55

66
#include "GS/GS.h"
7+
#include "GS/GSPerfMon.h"
78
#include "GS/GSLocalMemory.h"
89
#include "GS/GSDrawingContext.h"
910
#include "GS/GSDrawingEnvironment.h"
@@ -262,6 +263,9 @@ class GSState : public GSAlignedClass<32>
262263
static int s_last_transfer_draw_n;
263264
static int s_transfer_n;
264265

266+
GSPerfMon m_perfmon_frame; // Track stat across a frame.
267+
GSPerfMon m_perfmon_draw; // Track stat across a draw.
268+
265269
static constexpr u32 STATE_VERSION = 9;
266270

267271
enum REG_DIRTY

pcsx2/GS/GSUtil.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,44 @@ const char* GSUtil::GetACName(u32 ac)
176176
return (ac < std::size(names)) ? names[ac] : "";
177177
}
178178

179+
const char* GSUtil::GetPerfMonCounterName(GSPerfMon::counter_t counter, bool hw)
180+
{
181+
if (hw)
182+
{
183+
static constexpr const char* names_hw[] = {
184+
"Prim",
185+
"Draw",
186+
"DrawCalls",
187+
"Readbacks",
188+
"Swizzle",
189+
"Unswizzle",
190+
"TextureCopies",
191+
"TextureUploads",
192+
"Barriers",
193+
"RenderPasses",
194+
"CounterLast",
195+
};
196+
return counter < std::size(names_hw) ? names_hw[counter] : "";
197+
}
198+
else
199+
{
200+
static constexpr const char* names_sw[] = {
201+
"Prim",
202+
"Draw",
203+
"DrawCalls",
204+
"Readbacks",
205+
"Swizzle",
206+
"Unswizzle",
207+
"Fillrate",
208+
"SyncPoint",
209+
"Barriers",
210+
"RenderPasses",
211+
"CounterLast",
212+
};
213+
return counter < std::size(names_sw) ? names_sw[counter] : "";
214+
}
215+
}
216+
179217
const u32* GSUtil::HasSharedBitsPtr(u32 dpsm)
180218
{
181219
return s_maps.SharedBitsField[dpsm];

pcsx2/GS/GSUtil.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
#include "GS.h"
77
#include "GSRegs.h"
8+
#include "GSPerfMon.h"
89

910
class GSUtil
1011
{
@@ -25,6 +26,7 @@ class GSUtil
2526
static const char* GetTFXName(u32 tfx);
2627
static const char* GetTCCName(u32 tcc);
2728
static const char* GetACName(u32 ac);
29+
static const char* GetPerfMonCounterName(GSPerfMon::counter_t counter, bool hw = true);
2830

2931
static const u32* HasSharedBitsPtr(u32 dpsm);
3032
static bool HasSharedBits(u32 spsm, const u32* ptr);

0 commit comments

Comments
 (0)