mirror of
https://github.com/PCSX2/pcsx2.git
synced 2025-12-16 04:08:48 +00:00
GS: Allow dumping draw/frames stats.
This commit is contained in:
parent
6ab02e76f1
commit
be1af0cd0f
@ -446,8 +446,8 @@ static void PrintCommandLineHelp(const char* progname)
|
||||
std::fprintf(stderr, " -help: Displays this information and exits.\n");
|
||||
std::fprintf(stderr, " -version: Displays version information and exits.\n");
|
||||
std::fprintf(stderr, " -dumpdir <dir>: Frame dump directory (will be dumped as filename_frameN.png).\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices, transfers (list)), transfers (images), respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dump [rt|tex|z|f|a|i|tr|ds|fs]: Enabling dumping of render target, texture, z buffer, frame, "
|
||||
"alphas, and info (context, vertices, list of transfers), transfers images, draw stats, frame stats, respectively, per draw. Generates lots of data.\n");
|
||||
std::fprintf(stderr, " -dumprange N[,L,B]: Start dumping from draw N (base 0), stops after L draws, and only "
|
||||
"those draws that are multiples of B (intersection of -dumprange and -dumprangef used)."
|
||||
"Defaults to 0,-1,1 (all draws). Only used if -dump used.\n");
|
||||
@ -533,6 +533,10 @@ bool GSRunner::ParseCommandLineArgs(int argc, char* argv[], VMBootParameters& pa
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveInfo", true);
|
||||
if (str.find("tr") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveTransferImages", true);
|
||||
if (str.find("ds") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveDrawStats", true);
|
||||
if (str.find("fs") != std::string::npos)
|
||||
s_settings_interface.SetBoolValue("EmuCore/GS", "SaveFrameStats", true);
|
||||
continue;
|
||||
}
|
||||
else if (CHECK_ARG_PARAM("-dumprange"))
|
||||
|
||||
@ -71,7 +71,21 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="saveDrawStats">
|
||||
<property name="text">
|
||||
<string>Save Draw Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="saveFrameStats">
|
||||
<property name="text">
|
||||
<string>Save Frame Stats</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QCheckBox" name="saveTransferImages">
|
||||
<property name="text">
|
||||
<string>Save Transfer Image Data</string>
|
||||
|
||||
@ -110,6 +110,8 @@ DebugSettingsWidget::DebugSettingsWidget(SettingsWindow* settings_dialog, QWidge
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveAlpha, "EmuCore/GS", "SaveAlpha", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveInfo, "EmuCore/GS", "SaveInfo", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveTransferImages, "EmuCore/GS", "SaveTransferImages", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveDrawStats, "EmuCore/GS", "SaveDrawStats", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_gs.saveFrameStats, "EmuCore/GS", "SaveFrameStats", false);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawStart, "EmuCore/GS", "SaveDrawStart", 0);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveDrawCount, "EmuCore/GS", "SaveDrawCount", 5000);
|
||||
SettingWidgetBinder::BindWidgetToIntSetting(sif, m_gs.saveFrameStart, "EmuCore/GS", "SaveFrameStart", 0);
|
||||
@ -215,6 +217,8 @@ void DebugSettingsWidget::onDrawDumpingChanged()
|
||||
m_gs.saveAlpha->setEnabled(enabled);
|
||||
m_gs.saveInfo->setEnabled(enabled);
|
||||
m_gs.saveTransferImages->setEnabled(enabled);
|
||||
m_gs.saveDrawStats->setEnabled(enabled);
|
||||
m_gs.saveFrameStats->setEnabled(enabled);
|
||||
m_gs.saveDrawStart->setEnabled(enabled);
|
||||
m_gs.saveDrawCount->setEnabled(enabled);
|
||||
m_gs.saveFrameStart->setEnabled(enabled);
|
||||
|
||||
@ -778,6 +778,8 @@ struct Pcsx2Config
|
||||
SaveAlpha : 1,
|
||||
SaveInfo : 1,
|
||||
SaveTransferImages : 1,
|
||||
SaveDrawStats : 1,
|
||||
SaveFrameStats : 1,
|
||||
DumpReplaceableTextures : 1,
|
||||
DumpReplaceableMipmaps : 1,
|
||||
DumpTexturesWithFMVActive : 1,
|
||||
|
||||
@ -3,8 +3,10 @@
|
||||
|
||||
#include "GSPerfMon.h"
|
||||
#include "GS.h"
|
||||
#include "GSUtil.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <inttypes.h>
|
||||
|
||||
GSPerfMon g_perfmon;
|
||||
|
||||
@ -41,3 +43,28 @@ void GSPerfMon::Update()
|
||||
|
||||
memset(m_counters, 0, sizeof(m_counters));
|
||||
}
|
||||
|
||||
GSPerfMon GSPerfMon::operator-(const GSPerfMon& other)
|
||||
{
|
||||
GSPerfMon diff;
|
||||
for (std::size_t i = 0; i < std::size(diff.m_counters); i++)
|
||||
{
|
||||
diff.m_counters[i] = m_counters[i] - other.m_counters[i];
|
||||
}
|
||||
return diff;
|
||||
}
|
||||
|
||||
void GSPerfMon::Dump(const std::string& filename, bool hw)
|
||||
{
|
||||
FILE* fp = fopen(filename.c_str(), "w");
|
||||
if (!fp)
|
||||
return;
|
||||
|
||||
std::size_t last = hw ? CounterLastHW : CounterLastSW;
|
||||
for (std::size_t i = 0; i < last; i++)
|
||||
{
|
||||
fprintf(fp, "%s: %" PRIu64 "\n", GSUtil::GetPerfMonCounterName(static_cast<counter_t>(i), hw), static_cast<u64>(m_counters[i]));
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
#include "common/Pcsx2Defs.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
|
||||
class GSPerfMon
|
||||
{
|
||||
@ -27,6 +28,9 @@ public:
|
||||
// Reused counters for HW.
|
||||
TextureCopies = Fillrate,
|
||||
TextureUploads = SyncPoint,
|
||||
|
||||
CounterLastHW = CounterLast,
|
||||
CounterLastSW = SyncPoint + 1
|
||||
};
|
||||
|
||||
protected:
|
||||
@ -58,6 +62,10 @@ public:
|
||||
m_disp_fb_sprite_blits = 0;
|
||||
return blits;
|
||||
}
|
||||
|
||||
GSPerfMon operator-(const GSPerfMon& other);
|
||||
|
||||
void Dump(const std::string& filename, bool hw);
|
||||
};
|
||||
|
||||
extern GSPerfMon g_perfmon;
|
||||
@ -202,6 +202,9 @@ void GSState::Reset(bool hardware_reset)
|
||||
m_backed_up_ctx = -1;
|
||||
|
||||
memcpy(&m_prev_env, &m_env, sizeof(m_prev_env));
|
||||
|
||||
m_perfmon_draw.Reset();
|
||||
m_perfmon_frame.Reset();
|
||||
}
|
||||
|
||||
template<bool auto_flush>
|
||||
@ -2125,6 +2128,16 @@ void GSState::FlushPrim()
|
||||
g_perfmon.Put(GSPerfMon::Draw, 1);
|
||||
g_perfmon.Put(GSPerfMon::Prim, m_index.tail / GSUtil::GetVertexCount(PRIM->PRIM));
|
||||
|
||||
if (GSConfig.ShouldDump(s_n, g_perfmon.GetFrame()))
|
||||
{
|
||||
if (GSConfig.SaveDrawStats)
|
||||
{
|
||||
m_perfmon_draw = g_perfmon - m_perfmon_draw;
|
||||
m_perfmon_draw.Dump(GetDrawDumpPath("%05d_draw_stats.txt", s_n), GSIsHardwareRenderer());
|
||||
m_perfmon_draw = g_perfmon;
|
||||
}
|
||||
}
|
||||
|
||||
m_index.tail = 0;
|
||||
m_vertex.head = 0;
|
||||
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "GS/GS.h"
|
||||
#include "GS/GSPerfMon.h"
|
||||
#include "GS/GSLocalMemory.h"
|
||||
#include "GS/GSDrawingContext.h"
|
||||
#include "GS/GSDrawingEnvironment.h"
|
||||
@ -264,6 +265,9 @@ public:
|
||||
static int s_last_transfer_draw_n;
|
||||
static int s_transfer_n;
|
||||
|
||||
GSPerfMon m_perfmon_frame; // Track stat across a frame.
|
||||
GSPerfMon m_perfmon_draw; // Track stat across a draw.
|
||||
|
||||
static constexpr u32 STATE_VERSION = 9;
|
||||
|
||||
enum REG_DIRTY
|
||||
|
||||
@ -176,6 +176,40 @@ const char* GSUtil::GetACName(u32 ac)
|
||||
return (ac < std::size(names)) ? names[ac] : "";
|
||||
}
|
||||
|
||||
const char* GSUtil::GetPerfMonCounterName(GSPerfMon::counter_t counter, bool hw)
|
||||
{
|
||||
if (hw)
|
||||
{
|
||||
static constexpr const char* names_hw[GSPerfMon::CounterLastHW] = {
|
||||
"Prim",
|
||||
"Draw",
|
||||
"DrawCalls",
|
||||
"Readbacks",
|
||||
"Swizzle",
|
||||
"Unswizzle",
|
||||
"TextureCopies",
|
||||
"TextureUploads",
|
||||
"Barriers",
|
||||
"RenderPasses"
|
||||
};
|
||||
return counter < std::size(names_hw) ? names_hw[counter] : "";
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr const char* names_sw[GSPerfMon::CounterLastSW] = {
|
||||
"Prim",
|
||||
"Draw",
|
||||
"DrawCalls",
|
||||
"Readbacks",
|
||||
"Swizzle",
|
||||
"Unswizzle",
|
||||
"Fillrate",
|
||||
"SyncPoint"
|
||||
};
|
||||
return counter < std::size(names_sw) ? names_sw[counter] : "";
|
||||
}
|
||||
}
|
||||
|
||||
const u32* GSUtil::HasSharedBitsPtr(u32 dpsm)
|
||||
{
|
||||
return s_maps.SharedBitsField[dpsm];
|
||||
|
||||
@ -5,6 +5,7 @@
|
||||
|
||||
#include "GS.h"
|
||||
#include "GSRegs.h"
|
||||
#include "GSPerfMon.h"
|
||||
|
||||
class GSUtil
|
||||
{
|
||||
@ -25,6 +26,7 @@ public:
|
||||
static const char* GetTFXName(u32 tfx);
|
||||
static const char* GetTCCName(u32 tcc);
|
||||
static const char* GetACName(u32 ac);
|
||||
static const char* GetPerfMonCounterName(GSPerfMon::counter_t counter, bool hw = true);
|
||||
|
||||
static const u32* HasSharedBitsPtr(u32 dpsm);
|
||||
static bool HasSharedBits(u32 spsm, const u32* ptr);
|
||||
|
||||
@ -591,6 +591,13 @@ void GSRenderer::VSync(u32 field, bool registers_written, bool idle_frame)
|
||||
|
||||
if (GSConfig.SaveTransferImages)
|
||||
DumpTransferImages();
|
||||
|
||||
if (GSConfig.SaveFrameStats)
|
||||
{
|
||||
m_perfmon_frame = g_perfmon - m_perfmon_frame;
|
||||
m_perfmon_frame.Dump(GetDrawDumpPath("%05d_f%05lld_frame_stats.txt", s_n, g_perfmon.GetFrame()), GSIsHardwareRenderer());
|
||||
m_perfmon_frame = g_perfmon;
|
||||
}
|
||||
}
|
||||
|
||||
const int fb_sprite_blits = g_perfmon.GetDisplayFramebufferSpriteBlits();
|
||||
|
||||
@ -991,6 +991,8 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBoolEx(SaveAlpha, "SaveAlpha");
|
||||
SettingsWrapBitBoolEx(SaveInfo, "SaveInfo");
|
||||
SettingsWrapBitBoolEx(SaveTransferImages, "SaveTransferImages");
|
||||
SettingsWrapBitBoolEx(SaveDrawStats, "SaveDrawStats");
|
||||
SettingsWrapBitBoolEx(SaveFrameStats, "SaveFrameStats");
|
||||
SettingsWrapBitBool(DumpReplaceableTextures);
|
||||
SettingsWrapBitBool(DumpReplaceableMipmaps);
|
||||
SettingsWrapBitBool(DumpTexturesWithFMVActive);
|
||||
|
||||
Loading…
Reference in New Issue
Block a user