Just some refactoring of the GPUStatistics struct, and more use of StringWriter

This commit is contained in:
Henrik Rydgård
2026-05-29 14:13:34 +02:00
parent 3b6ecc4001
commit f60e27a9b7
62 changed files with 413 additions and 426 deletions
+1
View File
@@ -715,6 +715,7 @@ add_library(Common STATIC
Common/Data/Text/I18n.h
Common/Data/Text/Parsers.cpp
Common/Data/Text/Parsers.h
Common/Data/Text/StringWriter.h
Common/Data/Text/WrapText.cpp
Common/Data/Text/WrapText.h
Common/Data/Random/Rng.h
+1 -1
View File
@@ -57,7 +57,7 @@ public:
int SkipLineCRLF();
// Utility functions.
void Printf(const char *fmt, ...);
ATTR_FORMAT_PRINTF(2, 3) void Printf(MSVC_FORMAT_PRINTF const char *fmt, ...);
// Dumps the entire buffer to the string, but keeps it around.
// Only to be used for debugging, since it might not be fast at all.
+1
View File
@@ -411,6 +411,7 @@
<ClInclude Include="Data\Random\Rng.h" />
<ClInclude Include="Data\Text\I18n.h" />
<ClInclude Include="Data\Text\Parsers.h" />
<ClInclude Include="Data\Text\StringWriter.h" />
<ClInclude Include="Data\Text\WrapText.h" />
<ClInclude Include="FakeEmitter.h" />
<ClInclude Include="File\AndroidContentURI.h" />
+3
View File
@@ -781,6 +781,9 @@
<ClInclude Include="..\ext\pugixml\pugixml.hpp">
<Filter>ext\pugixml</Filter>
</ClInclude>
<ClInclude Include="Data\Text\StringWriter.h">
<Filter>Data\Text</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="ABI.cpp" />
+16
View File
@@ -132,3 +132,19 @@ inline u64 __rotr64(u64 x, unsigned int shift){
return (x >> n) | (x << (64 - n));
#endif
}
// --- GCC / Clang / Intel Definition ---
#if defined(__GNUC__) || defined(__clang__)
#define ATTR_FORMAT_PRINTF(fmt_idx, first_arg_idx) \
__attribute__((format(printf, fmt_idx, first_arg_idx)))
#else
#define ATTR_FORMAT_PRINTF(fmt_idx, first_arg_idx)
#endif
// --- MSVC Definition ---
#if defined(_MSC_VER)
#include <sal.h>
#define MSVC_FORMAT_PRINTF _Printf_format_string_
#else
#define MSVC_FORMAT_PRINTF
#endif
+1
View File
@@ -6,6 +6,7 @@
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/StringUtils.h"
// Not strictly a parser...
-71
View File
@@ -79,74 +79,3 @@ std::string NiceSizeFormat(uint64_t size);
// seconds, or minutes, or hours.
// Uses I18N strings.
std::string NiceTimeFormat(int seconds);
// Not a parser, needs a better location.
// Simplified version of ShaderWriter. Would like to have that inherit from this but can't figure out how
// due to the return value chaining.
// TODO: We actually also have Buffer, with .Printf(), which is almost as convenient. Should maybe improve that instead?
class StringWriter {
public:
StringWriter(char *buffer, size_t bufSize) : start_(buffer), p_(buffer), bufSize_(bufSize) {
buffer[0] = '\0';
}
template<size_t sz>
explicit StringWriter(char (&buffer)[sz]) : start_(buffer), p_(buffer), bufSize_(sz) {
buffer[0] = '\0';
}
StringWriter(const StringWriter &) = delete;
std::string_view as_view() const {
return std::string_view(start_, p_ - start_);
}
size_t size() const {
return p_ - start_;
}
// Assumes the input is zero-terminated.
// C: Copies a string literal (which always are zero-terminated, the count includes the zero) directly to the stream.
template<size_t T>
StringWriter &C(const char(&text)[T]) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= T)
return *this;
memcpy(p_, text, T);
p_ += T - 1;
return *this;
}
// Assumes the input is zero-terminated.
// C: Copies a string literal (which always are zero-terminated, the count includes the zero) directly to the stream.
StringWriter &B(bool b) {
return W(b ? "true" : "false");
}
// W: Writes a string_view to the stream.
StringWriter &W(std::string_view text) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= text.length())
return *this;
memcpy(p_, text.data(), text.length());
p_ += text.length();
*p_ = '\0';
return *this;
}
// F: Formats into the buffer.
StringWriter &F(const char *format, ...);
StringWriter &endl() {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= 2)
return *this;
return C("\n");
}
void Rewind(size_t offset) {
p_ -= offset;
}
private:
char *start_;
char *p_;
size_t bufSize_;
};
+2
View File
@@ -0,0 +1,2 @@
#include "Common/Data/Text/StringWriter.h"
+78
View File
@@ -0,0 +1,78 @@
#pragma once
#include <string>
#include <cstring> // for memcpy
#include "Common/CommonFuncs.h"
// Not a parser, needs a better location.
// Simplified version of ShaderWriter. Would like to have that inherit from this but can't figure out how
// due to the return value chaining. Maybe with the curiously recurring template pattern?
// TODO: We actually also have Buffer, with .Printf(), which is almost as convenient. Should maybe improve that instead?
class StringWriter {
public:
StringWriter(char *buffer, size_t bufSize) : start_(buffer), p_(buffer), bufSize_(bufSize) {
buffer[0] = '\0';
}
template<size_t sz>
explicit StringWriter(char(&buffer)[sz]) : start_(buffer), p_(buffer), bufSize_(sz) {
buffer[0] = '\0';
}
StringWriter(const StringWriter &) = delete;
std::string_view as_view() const {
return std::string_view(start_, p_ - start_);
}
size_t size() const {
return p_ - start_;
}
// Assumes the input is zero-terminated.
// C: Copies a string literal (which always are zero-terminated, the count includes the zero) directly to the stream.
template<size_t T>
StringWriter &C(const char(&text)[T]) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= T)
return *this;
memcpy(p_, text, T);
p_ += T - 1;
return *this;
}
// Assumes the input is zero-terminated.
// C: Copies a string literal (which always are zero-terminated, the count includes the zero) directly to the stream.
StringWriter &B(bool b) {
return W(b ? "true" : "false");
}
// W: Writes a string_view to the stream.
StringWriter &W(std::string_view text) {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= text.length())
return *this;
memcpy(p_, text.data(), text.length());
p_ += text.length();
*p_ = '\0';
return *this;
}
// F: Formats into the buffer.
// This one is implemented in Parsers.cpp.
StringWriter &F(MSVC_FORMAT_PRINTF const char *format, ...) ATTR_FORMAT_PRINTF(2, 3);
StringWriter &endl() {
const size_t remainder = bufSize_ - (p_ - start_);
if (remainder <= 2)
return *this;
return C("\n");
}
void Rewind(size_t offset) {
p_ -= offset;
}
private:
char *start_;
char *p_;
size_t bufSize_;
};
+3 -5
View File
@@ -4,6 +4,7 @@
#include <string>
#include <cstdint>
#include "Common/CommonFuncs.h"
#include "Common/GPU/OpenGL/GLCommon.h"
#include "Common/GPU/OpenGL/gl3stub.h"
@@ -25,11 +26,8 @@ public:
void BeginFrame();
void Begin(const char *fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 2, 3)))
#endif
;
ATTR_FORMAT_PRINTF(2, 3)
void Begin(MSVC_FORMAT_PRINTF const char *fmt, ...);
void End();
void SetEnabledPtr(bool *enabledPtr) {
+1
View File
@@ -35,6 +35,7 @@ enum class ShaderWriterFlags {
};
ENUM_CLASS_BITOPS(ShaderWriterFlags);
// TODO: Somehow merge with StringWriter from Parsers.h
class ShaderWriter {
public:
// Extensions are supported for both OpenGL ES and Vulkan (though of course, they're different).
+2 -5
View File
@@ -3,6 +3,7 @@
#include <vector>
#include <string>
#include "Common/CommonFuncs.h"
#include "VulkanLoader.h"
// Simple scoped based profiler, initially meant for instant one-time tasks like texture uploads
@@ -29,11 +30,7 @@ public:
void BeginFrame(VulkanContext *vulkan, VkCommandBuffer firstCommandBuffer);
void Begin(VkCommandBuffer cmdBuf, VkPipelineStageFlagBits stage, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 4, 5)))
#endif
;
ATTR_FORMAT_PRINTF(4, 5) void Begin(VkCommandBuffer cmdBuf, VkPipelineStageFlagBits stage, MSVC_FORMAT_PRINTF const char *fmt, ...);
void End(VkCommandBuffer cmdBuf, VkPipelineStageFlagBits stage);
void SetEnabledPtr(bool *enabledPtr) {
+1 -1
View File
@@ -896,7 +896,7 @@ public:
// Not very elegant, but more elegant than the old passId hack.
virtual void SetInvalidationCallback(InvalidationCallback callback) = 0;
// Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.numFlips
// Total amount of frames rendered. Unaffected by game pause, so more robust than gpuStats.totals.numFlips
virtual int GetFrameCount() = 0;
virtual std::string GetGpuProfileString() const {
+2 -10
View File
@@ -109,11 +109,7 @@ inline bool GenericLogEnabled(Log type, LogLevel level) {
return g_log[(int)type].IsEnabled(level) && (*g_bLogEnabledSetting);
}
void GenericLog(Log type, LogLevel level, const char *file, int line, const char *fmt, ...)
#ifdef __GNUC__
__attribute__((format(printf, 5, 6)))
#endif
;
ATTR_FORMAT_PRINTF(5, 6) void GenericLog(Log type, LogLevel level, const char *file, int line, MSVC_FORMAT_PRINTF const char *fmt, ...);
// If you want to see verbose logs, change this to VERBOSE_LEVEL.
@@ -134,11 +130,7 @@ void GenericLog(Log type, LogLevel level, const char *file, int line, const char
#define VERBOSE_LOG(t,...) do { GENERIC_LOG(t, LogLevel::LVERBOSE, __VA_ARGS__) } while (false)
// Currently only actually shows a dialog box on Windows.
bool HandleAssert(bool isDebugAssert, const char *function, const char *file, int line, const char *expression, const char* format, ...)
#ifdef __GNUC__
__attribute__((format(printf, 6, 7)))
#endif
;
ATTR_FORMAT_PRINTF(6, 7) bool HandleAssert(bool isDebugAssert, const char *function, const char *file, int line, const char *expression, MSVC_FORMAT_PRINTF const char *format, ...);
// These allow us to get a small amount of information into assert messages.
// They can have a value between 0 and 15.
+6 -6
View File
@@ -3,6 +3,7 @@
#include "Common/Math/math_util.h"
#include "Common/TimeUtil.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/StringUtils.h"
#include "Common/Log.h"
@@ -765,21 +766,20 @@ void ControlMapper::onVKey(VirtKey vkey, bool down) {
}
}
void ControlMapper::GetDebugString(char *buffer, size_t bufSize) const {
std::stringstream str;
void ControlMapper::GetDebugString(StringWriter &w) const {
for (auto &iter : curInput_) {
char temp[256];
iter.first.FormatDebug(temp, sizeof(temp));
str << temp << ": " << iter.second.value << std::endl;
w.F("%s: %f\n", temp, iter.second.value);
}
for (int i = 0; i < ARRAY_SIZE(virtKeys_); i++) {
int vkId = VIRTKEY_FIRST + i;
if ((vkId >= VIRTKEY_AXIS_X_MIN && vkId <= VIRTKEY_AXIS_Y_MAX) || vkId == VIRTKEY_ANALOG_LIGHTLY || vkId == VIRTKEY_SPEED_ANALOG) {
str << KeyMap::GetPspButtonName(vkId) << ": " << virtKeys_[i] << std::endl;
w.F("%s: %f\n", KeyMap::GetPspButtonName(vkId).c_str(), virtKeys_[i]);
}
}
str << "Lstick: " << converted_[0][0] << ", " << converted_[0][1] << std::endl;
truncate_cpy(buffer, bufSize, str.str().c_str());
w.F("Lstick: %f, %f\n", converted_[0][0], converted_[0][1]);
w.F("Rstick: %f, %f\n", converted_[1][0], converted_[1][1]);
}
void ControlMapper::RemoveListener(ControlListener *listener) {
+3 -1
View File
@@ -21,6 +21,8 @@ public:
virtual void SetRawAnalog(int stick, float x, float y) {}
};
class StringWriter;
// Utilities for mapping input events to PSP inputs and virtual keys.
// Main use is of course from EmuScreen.cpp, but also useful from control settings etc.
class ControlMapper {
@@ -56,7 +58,7 @@ public:
// Call when the emu screen gets pushed behind some other screen, like the pause screen, to release all "down" inputs.
void ReleaseAll();
void GetDebugString(char *buffer, size_t bufSize) const;
void GetDebugString(StringWriter &w) const;
struct InputSample {
float value;
@@ -17,6 +17,8 @@
#include <mutex>
#include <vector>
#include "Common/Data/Text/StringWriter.h"
#include "Core/Debugger/WebSocket/GPUStatsSubscriber.h"
#include "Core/HW/Display.h"
#include "Core/System.h"
@@ -120,7 +122,9 @@ void WebSocketGPUStatsState::FlipListener() {
CollectedStats &stats = pendingStats_[pendingStats_.size() - 1];
__DisplayGetFPS(&stats.vps, &stats.fps, &stats.actual_fps);
__DisplayGetDebugStats(stats.statbuf, sizeof(stats.statbuf));
StringWriter w(stats.statbuf);
__DisplayGetDebugStats(w);
int valid;
float *sleepHistory;
+1 -4
View File
@@ -190,11 +190,8 @@ void hleDoLogInternal(Log t, LogLevel level, u64 res, const char *file, int line
template <bool leave, bool convert_code, typename T>
[[nodiscard]]
#ifdef __GNUC__
__attribute__((format(printf, 7, 8)))
#endif
NO_INLINE
T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag, const char *reasonFmt, ...) {
ATTR_FORMAT_PRINTF(7, 8) T hleDoLog(Log t, LogLevel level, T res, const char *file, int line, const char *reportTag, MSVC_FORMAT_PRINTF const char *reasonFmt, ...) {
if (!GenericLogEnabled(t, level)) {
if (leave) {
hleLeave();
+5 -3
View File
@@ -28,6 +28,7 @@
#endif
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/Profiler/Profiler.h"
#include "Common/System/System.h"
#include "Common/System/OSD.h"
@@ -273,7 +274,7 @@ void __DisplayDoState(PointerWrap &p) {
gstate_c.DoState(p);
if (s < 2) {
// This shouldn't have been savestated anyway, but it was.
// It's unlikely to overlap with the first value in gpuStats.
// It's unlikely to overlap with the first value in gpuStats.perFrame.
int gpuVendorTemp = 0;
p.ExpectVoid(&gpuVendorTemp, sizeof(gpuVendorTemp));
}
@@ -395,7 +396,8 @@ static void DoFrameDropLogging(float scaledTimestep) {
const double actualTimestep = curFrameTime - lastFrameTime;
char stats[4096];
__DisplayGetDebugStats(stats, sizeof(stats));
StringWriter w(stats);
__DisplayGetDebugStats(w);
NOTICE_LOG(Log::sceDisplay, "Dropping frames - budget = %.2fms / %.1ffps, actual = %.2fms (+%.2fms) / %.1ffps\n%s", scaledTimestep * 1000.0, 1.0 / scaledTimestep, actualTimestep * 1000.0, (actualTimestep - scaledTimestep) * 1000.0, 1.0 / actualTimestep, stats);
}
}
@@ -674,7 +676,7 @@ void __DisplayFlip(int cyclesLate) {
}
if (fbDirty) {
gpuStats.numFlips++;
gpuStats.totals.numFlips++;
}
float scaledTimestep = (float)numVBlanksSinceFlip * timePerVblank;
+2 -2
View File
@@ -21,7 +21,6 @@
#include "zlib.h"
#include "Common/Data/Convert/SmallDataConvert.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Serialize/Serializer.h"
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/Serialize/SerializeSet.h"
@@ -31,6 +30,7 @@
#include "Common/System/System.h"
#include "Common/System/OSD.h"
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Text/StringWriter.h"
#include "Core/Config.h"
#include "Core/Core.h"
@@ -363,7 +363,7 @@ void PSPModule::GetLongInfo(char *ptr, int bufSize) const {
}
w.F("Text: %08x (%08x bytes)\n", nm.text_addr, nm.text_size);
w.F("Data: %08x (%08x bytes)\n", GetDataAddr(), nm.data_size);
w.F("BSS: % 08x(% 08x bytes)\n", GetBSSAddr(), nm.bss_size);
w.F("BSS: %08x (%08x bytes)\n", GetBSSAddr(), nm.bss_size);
w.F("Entry: %08x GP: %08x\n", nm.entry_addr, nm.gp_value);
w.F("Status: %08x\n", nm.status);
}
+1
View File
@@ -22,6 +22,7 @@
#include "Common/Net/Resolve.h"
#include "Common/Net/SocketCompat.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/Data/Text/I18n.h"
#include "Common/File/VFS/VFS.h"
#include "Common/File/FileUtil.h"
+6 -17
View File
@@ -23,6 +23,7 @@
#include "Common/Serialize/SerializeFuncs.h"
#include "Common/System/System.h"
#include "Common/TimeUtil.h"
#include "Common/Data/Text/StringWriter.h"
#include "Core/Config.h"
#include "Core/System.h"
#include "Core/CoreTiming.h"
@@ -79,10 +80,10 @@ static void CalculateFPS() {
actualFps = (float)(actualFlips - lastActualFlips);
fps = frames / (now - lastFpsTime);
flips = (float)(g_Config.iDisplayRefreshRate * (double)(gpuStats.numFlips - lastNumFlips) / frames);
flips = (float)(g_Config.iDisplayRefreshRate * (double)(gpuStats.totals.numFlips - lastNumFlips) / frames);
lastFpsFrame = numVBlanks;
lastNumFlips = gpuStats.numFlips;
lastNumFlips = gpuStats.totals.numFlips;
lastActualFlips = actualFlips;
lastFpsTime = now;
@@ -187,24 +188,12 @@ void DisplayNotifySleep(double t, int pos) {
frameSleepHistory[pos] += t;
}
void __DisplayGetDebugStats(char *stats, size_t bufsize) {
char statbuf[4096];
void __DisplayGetDebugStats(StringWriter &w) {
if (!gpu) {
snprintf(stats, bufsize, "N/A");
w.C("No GPU stats available").endl();
return;
}
gpu->GetStats(statbuf, sizeof(statbuf));
snprintf(stats, bufsize,
"Kernel processing time: %0.2f ms\n"
"Slowest syscall: %s : %0.2f ms\n"
"Most active syscall: %s : %0.2f ms\n%s",
kernelStats.msInSyscalls * 1000.0f,
kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)",
kernelStats.slowestSyscallTime * 1000.0f,
kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)",
kernelStats.summedSlowestSyscallTime * 1000.0f,
statbuf);
gpu->GetStats(w);
}
// On like 90hz, 144hz, etc, we return 60.0f as the framerate target. We only target other
+2 -1
View File
@@ -21,6 +21,7 @@
#include <functional>
class PointerWrap;
class StringWriter;
typedef void (*FlipCallback)(void *userdata);
void __DisplayListenFlip(FlipCallback callback, void *userdata);
@@ -35,7 +36,7 @@ uint32_t __DisplayGetCurrentHcount();
uint32_t __DisplayGetAccumulatedHcount();
void DisplayAdjustAccumulatedHcount(uint32_t diff);
void __DisplayGetDebugStats(char *stats, size_t bufsize);
void __DisplayGetDebugStats(StringWriter &w);
void __DisplayGetAveragedFPS(float *out_vps, float *out_fps);
void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps);
void __DisplayGetVPS(float *out_vps);
+6 -6
View File
@@ -911,7 +911,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(std::string_view text, const PPGeSty
auto cacheItem = textDrawerImages.find(key);
if (cacheItem != textDrawerImages.end()) {
im = cacheItem->second;
cacheItem->second.entry.lastUsedFrame = gpuStats.numFlips;
cacheItem->second.entry.lastUsedFrame = gpuStats.totals.numFlips;
} else {
std::vector<uint8_t> bitmapData;
textDrawer->SetFontScale(style.scale, style.scale);
@@ -944,7 +944,7 @@ static PPGeTextDrawerImage PPGeGetTextImage(std::string_view text, const PPGeSty
memset(ramPtr + im.entry.bmHeight * bufwBytes, 0, bufwBytes + sz - origSz);
}
im.entry.lastUsedFrame = gpuStats.numFlips;
im.entry.lastUsedFrame = gpuStats.totals.numFlips;
textDrawerImages[key] = im;
}
@@ -1049,7 +1049,7 @@ static void PPGeDrawTextImage(const PPGeTextDrawerImage &im, float x, float y, c
static void PPGeDecimateTextImages(int age) {
// Do this always, in case the platform has no TextDrawer but save state did.
for (auto it = textDrawerImages.begin(); it != textDrawerImages.end(); ) {
if (gpuStats.numFlips - it->second.entry.lastUsedFrame >= age) {
if (gpuStats.totals.numFlips - it->second.entry.lastUsedFrame >= age) {
kernelMemory.Free(it->second.ptr);
it = textDrawerImages.erase(it);
} else {
@@ -1409,7 +1409,7 @@ bool PPGeImage::Load() {
Memory::Memset(texture_ + dataSize, 0, texSize - dataSize, "PPGeTexClear");
free(textureData);
lastFrame_ = gpuStats.numFlips;
lastFrame_ = gpuStats.totals.numFlips;
loadedTextures_.push_back(this);
return true;
}
@@ -1467,7 +1467,7 @@ void PPGeImage::CompatLoad(u32 texture, int width, int height) {
}
void PPGeImage::Decimate(int age) {
int tooOldFrame = gpuStats.numFlips - age;
int tooOldFrame = gpuStats.totals.numFlips - age;
for (size_t i = 0; i < loadedTextures_.size(); ++i) {
if (loadedTextures_[i]->lastFrame_ < tooOldFrame) {
loadedTextures_[i]->Free();
@@ -1484,7 +1484,7 @@ void PPGeImage::SetTexture() {
}
if (texture_ != 0) {
lastFrame_ = gpuStats.numFlips;
lastFrame_ = gpuStats.totals.numFlips;
PPGeSetTexture(texture_, width_, height_);
} else {
PPGeDisableTexture();
+7 -7
View File
@@ -518,7 +518,7 @@ int DepthRasterClipIndexedTriangles(int *tx, int *ty, float *tz, const float *tr
// Still good for backface culling early and pretty cheap to compute.
Vec4F32 doubleTriArea = (x1 - x0) * (y2 - y0) - (x2 - x0) * (y1 - y0) - Vec4F32::Splat((float)(MIN_TWICE_TRI_AREA));
if (!AnyZeroSignBit(doubleTriArea)) {
gpuStats.numDepthRasterEarlySize += 4;
gpuStats.perFrame.numDepthRasterEarlySize += 4;
continue;
}
@@ -560,8 +560,8 @@ int DepthRasterClipIndexedTriangles(int *tx, int *ty, float *tz, const float *tr
}
}
gpuStats.numDepthRasterZCulled += planeCulled;
gpuStats.numDepthEarlyBoxCulled += boxCulled;
gpuStats.perFrame.numDepthRasterZCulled += planeCulled;
gpuStats.perFrame.numDepthEarlyBoxCulled += boxCulled;
return outCount;
}
@@ -578,7 +578,7 @@ void DepthRasterScreenVerts(uint16_t *depth, int depthStride, const int *tx, con
// We remove the subpixel information here.
DepthRasterRect(depth, depthStride, scissor, tx[i], ty[i], tx[i + 1], ty[i + 1], z, draw.compareMode);
}
gpuStats.numDepthRasterPrims += count / 2;
gpuStats.perFrame.numDepthRasterPrims += count / 2;
break;
case GE_PRIM_TRIANGLES:
{
@@ -633,9 +633,9 @@ void DepthRasterScreenVerts(uint16_t *depth, int depthStride, const int *tx, con
}
}
}
gpuStats.numDepthRasterNoPixels += stats[(int)TriangleStat::NoPixels];
gpuStats.numDepthRasterTooSmall += stats[(int)TriangleStat::SmallOrBackface];
gpuStats.numDepthRasterPrims += stats[(int)TriangleStat::OK];
gpuStats.perFrame.numDepthRasterNoPixels += stats[(int)TriangleStat::NoPixels];
gpuStats.perFrame.numDepthRasterTooSmall += stats[(int)TriangleStat::SmallOrBackface];
gpuStats.perFrame.numDepthRasterPrims += stats[(int)TriangleStat::OK];
break;
}
default:
+6 -6
View File
@@ -571,7 +571,7 @@ void DrawEngineCommon::ApplyFramebufferRead(FBOTexState *fboTexState) {
if (gstate_c.Use(GPU_USE_FRAMEBUFFER_FETCH)) {
*fboTexState = FBO_TEX_READ_FRAMEBUFFER;
} else {
gpuStats.numCopiesForShaderBlend++;
gpuStats.perFrame.numCopiesForShaderBlend++;
*fboTexState = FBO_TEX_COPY_BIND_TEX;
}
gstate_c.Dirty(DIRTY_SHADERBLEND);
@@ -1037,7 +1037,7 @@ void DrawEngineCommon::DepthRasterSubmitRaw(GEPrimitiveType prim, const VertexDe
return;
}
TimeCollector collectStat(&gpuStats.msPrepareDepth, coreCollectDebugStats);
TimeCollector collectStat(&gpuStats.perFrame.msPrepareDepth, coreCollectDebugStats);
// Decode.
int numDecoded = 0;
@@ -1079,7 +1079,7 @@ void DrawEngineCommon::DepthRasterPredecoded(GEPrimitiveType prim, const void *i
return;
}
TimeCollector collectStat(&gpuStats.msPrepareDepth, coreCollectDebugStats);
TimeCollector collectStat(&gpuStats.perFrame.msPrepareDepth, coreCollectDebugStats);
// Make sure these have already been indexed away.
_dbg_assert_(prim != GE_PRIM_TRIANGLE_STRIP && prim != GE_PRIM_TRIANGLE_FAN);
@@ -1112,7 +1112,7 @@ void DrawEngineCommon::DepthRasterPredecoded(GEPrimitiveType prim, const void *i
void DrawEngineCommon::FlushQueuedDepth() {
if (rasterTimeStart_ != 0.0) {
gpuStats.msRasterTimeAvailable += time_now_d() - rasterTimeStart_;
gpuStats.perFrame.msRasterTimeAvailable += time_now_d() - rasterTimeStart_;
rasterTimeStart_ = 0.0;
}
@@ -1131,7 +1131,7 @@ void DrawEngineCommon::FlushQueuedDepth() {
DepthScissor tileScissor = draw.scissor.Tile(0, 1);
{
TimeCollector collectStat(&gpuStats.msCullDepth, collectStats);
TimeCollector collectStat(&gpuStats.perFrame.msCullDepth, collectStats);
switch (draw.prim) {
case GE_PRIM_RECTANGLES:
outVertCount = DepthRasterClipIndexedRectangles(tx, ty, tz, vertices, indices, draw, tileScissor);
@@ -1145,7 +1145,7 @@ void DrawEngineCommon::FlushQueuedDepth() {
}
}
if (outVertCount > 0) {
TimeCollector collectStat(&gpuStats.msRasterizeDepth, collectStats);
TimeCollector collectStat(&gpuStats.perFrame.msRasterizeDepth, collectStats);
if (!Memory::IsValid4AlignedAddress(draw.depthAddr)) {
continue;
}
+5 -5
View File
@@ -213,11 +213,11 @@ protected:
}
inline void ResetAfterDrawInline() {
gpuStats.numFlushes++;
gpuStats.numDrawCalls += numDrawInds_;
gpuStats.numVertexDecodes += numDrawVerts_;
gpuStats.numVertsSubmitted += vertexCountInDrawCalls_;
gpuStats.numVertsDecoded += numDecodedVerts_;
gpuStats.perFrame.numFlushes++;
gpuStats.perFrame.numDrawCalls += numDrawInds_;
gpuStats.perFrame.numVertexDecodes += numDrawVerts_;
gpuStats.perFrame.numVertsSubmitted += vertexCountInDrawCalls_;
gpuStats.perFrame.numVertsDecoded += numDecodedVerts_;
indexGen.Reset();
numDecodedVerts_ = 0;
+39 -39
View File
@@ -479,8 +479,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
// If it's newly wrong, or changing every frame, just keep track.
vfb->newWidth = drawing_width;
vfb->newHeight = drawing_height;
vfb->lastFrameNewSize = gpuStats.numFlips;
} else if (vfb->lastFrameNewSize + FBO_OLD_AGE < gpuStats.numFlips) {
vfb->lastFrameNewSize = gpuStats.totals.numFlips;
} else if (vfb->lastFrameNewSize + FBO_OLD_AGE < gpuStats.totals.numFlips) {
// Okay, it's changed for a while (and stayed that way.) Let's start over.
// But only if we really need to, to avoid blinking.
bool needsRecreate = vfb->bufferWidth > params.fb_stride;
@@ -502,7 +502,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
}
} else {
// It's not different, let's keep track of that too.
vfb->lastFrameNewSize = gpuStats.numFlips;
vfb->lastFrameNewSize = gpuStats.totals.numFlips;
}
if (!resized && renderScaleFactor_ != 1 && vfb->renderScaleFactor == 1) {
@@ -530,7 +530,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
vfb->height = drawing_height;
vfb->newWidth = drawing_width;
vfb->newHeight = drawing_height;
vfb->lastFrameNewSize = gpuStats.numFlips;
vfb->lastFrameNewSize = gpuStats.totals.numFlips;
vfb->fb_format = params.fb_format;
vfb->usageFlags = FB_USAGE_RENDER_COLOR;
@@ -557,8 +557,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
INFO_LOG(Log::FrameBuf, "Creating FBO for %08x (z: %08x) : %d x %d x %s", vfb->fb_address, vfb->z_address, vfb->width, vfb->height, GeBufferFormatToString(vfb->fb_format));
vfb->last_frame_render = gpuStats.numFlips;
frameLastFramebufUsed_ = gpuStats.numFlips;
vfb->last_frame_render = gpuStats.totals.numFlips;
frameLastFramebufUsed_ = gpuStats.totals.numFlips;
vfbs_.push_back(vfb);
currentRenderVfb_ = vfb;
@@ -577,8 +577,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
// Use it as a render target.
DEBUG_LOG(Log::FrameBuf, "Switching render target to FBO for %08x: %d x %d x %d ", vfb->fb_address, vfb->width, vfb->height, vfb->fb_format);
vfb->usageFlags |= FB_USAGE_RENDER_COLOR;
vfb->last_frame_render = gpuStats.numFlips;
frameLastFramebufUsed_ = gpuStats.numFlips;
vfb->last_frame_render = gpuStats.totals.numFlips;
frameLastFramebufUsed_ = gpuStats.totals.numFlips;
vfb->dirtyAfterDisplay = true;
if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0)
vfb->reallyDirtyAfterDisplay = true;
@@ -593,8 +593,8 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(Framebuffer
} else {
// Something changed, but we still got the same framebuffer we were already rendering to.
// Might not be a lot to do here, we check in NotifyRenderFramebufferUpdated
vfb->last_frame_render = gpuStats.numFlips;
frameLastFramebufUsed_ = gpuStats.numFlips;
vfb->last_frame_render = gpuStats.totals.numFlips;
frameLastFramebufUsed_ = gpuStats.totals.numFlips;
vfb->dirtyAfterDisplay = true;
if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0)
vfb->reallyDirtyAfterDisplay = true;
@@ -715,8 +715,8 @@ void FramebufferManagerCommon::CopyToDepthFromOverlappingFramebuffers(VirtualFra
if (source.channel == RASTER_DEPTH) {
// Good old depth->depth copy.
BlitFramebufferDepth(source.vfb, dest);
gpuStats.numDepthCopies++;
dest->last_frame_depth_updated = gpuStats.numFlips;
gpuStats.perFrame.numDepthCopies++;
dest->last_frame_depth_updated = gpuStats.totals.numFlips;
} else if (source.channel == RASTER_COLOR && draw_->GetDeviceCaps().fragmentShaderDepthWriteSupported) {
VirtualFramebuffer *src = source.vfb;
if (src->fb_format != GE_FORMAT_565) {
@@ -730,7 +730,7 @@ void FramebufferManagerCommon::CopyToDepthFromOverlappingFramebuffers(VirtualFra
shader = DRAW2D_565_TO_DEPTH_DESWIZZLE;
}
gpuStats.numReinterpretCopies++;
gpuStats.perFrame.numReinterpretCopies++;
src->usageFlags |= FB_USAGE_COLOR_MIXED_DEPTH;
dest->usageFlags |= FB_USAGE_COLOR_MIXED_DEPTH;
@@ -879,7 +879,7 @@ void FramebufferManagerCommon::CopyToColorFromOverlappingFramebuffers(VirtualFra
const char *pass_name = "N/A";
float scaleFactorX = 1.0f;
if (src->fb_format == dst->fb_format) {
gpuStats.numColorCopies++;
gpuStats.perFrame.numColorCopies++;
pipeline = Get2DPipeline(DRAW2D_COPY_COLOR);
pass_name = "copy_color";
} else {
@@ -898,7 +898,7 @@ void FramebufferManagerCommon::CopyToColorFromOverlappingFramebuffers(VirtualFra
pass_name = reinterpretStrings[(int)src->fb_format][(int)dst->fb_format];
gpuStats.numReinterpretCopies++;
gpuStats.perFrame.numReinterpretCopies++;
}
if (pipeline) {
@@ -1137,7 +1137,7 @@ void FramebufferManagerCommon::PerformWriteFormattedFromMemory(u32 addr, int siz
VirtualFramebuffer *vfb = ResolveVFB(addr, stride, fmt);
if (vfb) {
// Let's count this as a "render". This will also force us to use the correct format.
vfb->last_frame_render = gpuStats.numFlips;
vfb->last_frame_render = gpuStats.totals.numFlips;
vfb->colorBindSeq = GetBindSeqCount();
if (vfb->fb_stride < stride) {
@@ -1173,7 +1173,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size) {
if (useBufferedRendering_ && vfb->fbo) {
GEBufferFormat fmt = vfb->fb_format;
if (vfb->last_frame_render + 1 < gpuStats.numFlips && isDisplayBuf) {
if (vfb->last_frame_render + 1 < gpuStats.totals.numFlips && isDisplayBuf) {
// If we're not rendering to it, format may be wrong. Use displayFormat_ instead.
// TODO: This doesn't seem quite right anymore.
fmt = displayFormat_;
@@ -1307,7 +1307,7 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF
if (!partial && (flags & BINDFBCOLOR_UNCACHED) == 0) {
currentFramebufferCopy_ = renderCopy;
}
gpuStats.numCopiesForSelfTex++;
gpuStats.perFrame.numCopiesForSelfTex++;
} else {
// Failed to get temp FBO? Weird.
draw_->BindFramebufferAsTexture(framebuffer->fbo, stage, Draw::Aspect::COLOR_BIT, layer);
@@ -1487,7 +1487,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G
for (auto &iter : drawPixelsCache_) {
if (iter.contentsHash == imageHash && iter.tex->Width() == width && iter.tex->Height() == height && iter.tex->Format() == texFormat) {
iter.frameNumber = frameNumber;
gpuStats.numCachedUploads++;
gpuStats.perFrame.numCachedUploads++;
return iter.tex;
}
}
@@ -1499,7 +1499,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G
}
// OK, current one seems good, let's use it (and mark it used).
gpuStats.numUploads++;
gpuStats.perFrame.numUploads++;
draw_->UpdateTextureLevels(iter.tex, &srcPixels, generateTexture, 1);
// NOTE: numFlips is no good - this is called every frame when paused sometimes!
iter.frameNumber = frameNumber;
@@ -1536,7 +1536,7 @@ Draw::Texture *FramebufferManagerCommon::MakePixelTexture(const u8 *srcPixels, G
DrawPixelsEntry entry{ tex, imageHash, frameNumber };
drawPixelsCache_.push_back(entry);
gpuStats.numUploads++;
gpuStats.perFrame.numUploads++;
return tex;
}
@@ -1677,7 +1677,7 @@ void FramebufferManagerCommon::PrepareCopyDisplayToOutput(const DisplayLayoutCon
}
vfb->usageFlags |= FB_USAGE_DISPLAYED_FRAMEBUFFER;
vfb->last_frame_displayed = gpuStats.numFlips;
vfb->last_frame_displayed = gpuStats.totals.numFlips;
vfb->dirtyAfterDisplay = false;
vfb->reallyDirtyAfterDisplay = false;
@@ -1874,7 +1874,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
}
return;
}
if (!old.fbo && vfb->last_frame_failed != 0 && vfb->last_frame_failed - gpuStats.numFlips < 63) {
if (!old.fbo && vfb->last_frame_failed != 0 && vfb->last_frame_failed - gpuStats.totals.numFlips < 63) {
// Don't constantly retry FBOs which failed to create.
return;
}
@@ -1883,7 +1883,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
char tag[128];
size_t len = FormatFramebufferName(vfb, tag, sizeof(tag));
gpuStats.numFBOsCreated++;
gpuStats.perFrame.numFBOsCreated++;
vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, GetFramebufferLayers(), msaaLevel_, true, tag });
if (Memory::IsVRAMAddress(vfb->fb_address) && vfb->fb_stride != 0) {
@@ -1915,7 +1915,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
if (!vfb->fbo) {
ERROR_LOG(Log::FrameBuf, "Error creating FBO during resize! %dx%d", vfb->renderWidth, vfb->renderHeight);
vfb->last_frame_failed = gpuStats.numFlips;
vfb->last_frame_failed = gpuStats.totals.numFlips;
}
}
@@ -2024,7 +2024,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
continue;
}
if ((u32)size > vfb_size + 0x1000 && vfb->fb_format != GE_FORMAT_8888 && vfb->last_frame_render < gpuStats.numFlips) {
if ((u32)size > vfb_size + 0x1000 && vfb->fb_format != GE_FORMAT_8888 && vfb->last_frame_render < gpuStats.totals.numFlips) {
// Seems likely we are looking at a potential copy of 32-bit pixels (like video) to an old 16-bit buffer,
// which is very likely simply the wrong target, so skip it. See issue #17740 where this happens in Naruto Ultimate Ninja Heroes 2.
// Probably no point to give it a bad score and let it pass to sorting, as we're pretty sure here.
@@ -2165,7 +2165,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
}
}
if (dstBuffer) {
dstBuffer->last_frame_used = gpuStats.numFlips;
dstBuffer->last_frame_used = gpuStats.totals.numFlips;
if (channel == RASTER_DEPTH && !srcBuffer)
dstBuffer->usageFlags |= FB_USAGE_COLOR_MIXED_DEPTH;
}
@@ -2185,7 +2185,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size,
return false;
} else if (dstBuffer) {
if (flags & GPUCopyFlag::MEMSET) {
gpuStats.numClears++;
gpuStats.perFrame.numClears++;
WARN_LOG_N_TIMES(btucpy, 5, Log::FrameBuf, "Memcpy fbo memset-clear %08x (size: %x)", dst, size);
} else {
WARN_LOG_N_TIMES(btucpy, 5, Log::FrameBuf, "Memcpy fbo upload %08x -> %08x (size: %x)", src, dst, size);
@@ -2411,7 +2411,7 @@ VirtualFramebuffer *FramebufferManagerCommon::CreateRAMFramebuffer(uint32_t fbAd
vfb->height = height;
vfb->newWidth = vfb->width;
vfb->newHeight = vfb->height;
vfb->lastFrameNewSize = gpuStats.numFlips;
vfb->lastFrameNewSize = gpuStats.totals.numFlips;
vfb->renderScaleFactor = renderScaleFactor_;
vfb->renderWidth = (u16)(vfb->width * renderScaleFactor_);
vfb->renderHeight = (u16)(vfb->height * renderScaleFactor_);
@@ -2496,7 +2496,7 @@ VirtualFramebuffer *FramebufferManagerCommon::FindDownloadTempBuffer(VirtualFram
}
nvfb->usageFlags |= FB_USAGE_RENDER_COLOR;
nvfb->last_frame_render = gpuStats.numFlips;
nvfb->last_frame_render = gpuStats.totals.numFlips;
nvfb->dirtyAfterDisplay = true;
return nvfb;
@@ -2657,7 +2657,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst
}
if (dstBuffer) {
dstRect.vfb->last_frame_used = gpuStats.numFlips;
dstRect.vfb->last_frame_used = gpuStats.totals.numFlips;
// Mark the destination as fresh.
if (dstRect.channel == RASTER_COLOR) {
dstRect.vfb->colorBindSeq = GetBindSeqCount();
@@ -2760,7 +2760,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst
srcX1 /= scaleFactorX;
srcX2 /= scaleFactorX;
gpuStats.numReinterpretCopies++;
gpuStats.perFrame.numReinterpretCopies++;
FlushBeforeCopy();
BlitUsingRaster(src->fbo, srcX1, srcY1, srcX2, srcY2,
dst->fbo, dstX1, dstY1, dstX2, dstY2, false, dst->renderScaleFactor, pipeline, pass_name);
@@ -2875,7 +2875,7 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS
// Make sure we don't flop back and forth.
dstRect.vfb->newWidth = std::max(dstRect.w_bytes / bpp, (int)dstRect.vfb->width);
dstRect.vfb->newHeight = std::max(dstRect.h, (int)dstRect.vfb->height);
dstRect.vfb->lastFrameNewSize = gpuStats.numFlips;
dstRect.vfb->lastFrameNewSize = gpuStats.totals.numFlips;
// Resizing may change the viewport/etc.
gstate_c.Dirty(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_CULLRANGE);
}
@@ -2979,7 +2979,7 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u
u64 key = ((u64)reason << 48) | ((u32)w << 16) | h;
auto it = tempFBOs_.find(key);
if (it != tempFBOs_.end()) {
it->second.last_frame_used = gpuStats.numFlips;
it->second.last_frame_used = gpuStats.totals.numFlips;
return it->second.fbo;
}
@@ -2992,7 +2992,7 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(TempFBO reason, u16 w, u
return nullptr;
}
const TempFBOInfo info = { fbo, gpuStats.numFlips };
const TempFBOInfo info = { fbo, gpuStats.totals.numFlips };
tempFBOs_[key] = info;
return fbo;
}
@@ -3255,9 +3255,9 @@ void FramebufferManagerCommon::ReadbackFramebuffer(VirtualFramebuffer *vfb, int
NotifyMemInfo(MemBlockFlags::WRITE, fb_address + dstByteOffset, dstSize, tag, len);
if (mode == Draw::ReadbackMode::BLOCK) {
gpuStats.numBlockingReadbacks++;
gpuStats.perFrame.numBlockingReadbacks++;
} else {
gpuStats.numReadbacks++;
gpuStats.perFrame.numReadbacks++;
}
}
@@ -3294,8 +3294,8 @@ void FramebufferManagerCommon::ReadFramebufferToMemory(VirtualFramebuffer *vfb,
static int frameLastCopy = 0;
static u32 bufferLastCopy = 0;
static int copiesThisFrame = 0;
if (frameLastCopy != gpuStats.numFlips || bufferLastCopy != vfb->fb_address) {
frameLastCopy = gpuStats.numFlips;
if (frameLastCopy != gpuStats.totals.numFlips || bufferLastCopy != vfb->fb_address) {
frameLastCopy = gpuStats.totals.numFlips;
bufferLastCopy = vfb->fb_address;
copiesThisFrame = 0;
}
+1 -1
View File
@@ -313,7 +313,7 @@ public:
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason, bool *changed) {
// Inlining this part since it's so frequent.
if (!framebufChanged && currentRenderVfb_) {
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
currentRenderVfb_->last_frame_render = gpuStats.totals.numFlips;
currentRenderVfb_->dirtyAfterDisplay = true;
if (!skipDrawReason)
currentRenderVfb_->reallyDirtyAfterDisplay = true;
+3 -1
View File
@@ -214,6 +214,8 @@ struct GPUDebugVertex {
float nz;
};
class StringWriter;
class GPUDebugInterface {
public:
virtual ~GPUDebugInterface() = default;
@@ -236,7 +238,7 @@ public:
virtual void SetCmdValue(u32 op) = 0;
virtual void Flush() = 0;
virtual void GetStats(char *buffer, size_t bufsize) = 0;
virtual void GetStats(StringWriter &w) = 0;
virtual uint32_t SetAddrTranslation(uint32_t value) = 0;
virtual uint32_t GetAddrTranslation() = 0;
+2 -2
View File
@@ -233,7 +233,7 @@ void SoftwareTransform::Transform(int prim, u32 vertType, const DecVtxFormat &de
result->color = transformed[1].color0_32;
result->depth = depth;
result->action = SW_CLEAR;
gpuStats.numClears++;
gpuStats.perFrame.numClears++;
return;
}
}
@@ -556,7 +556,7 @@ void SoftwareTransform::ProjectClipAndExpand(int prim, int vertexCount, u32 vert
}
if (gstate.isModeClear()) {
gpuStats.numClears++;
gpuStats.perFrame.numClears++;
}
result->action = SW_DRAW_INDEXED;
+26 -26
View File
@@ -150,8 +150,8 @@ void TextureCacheCommon::StartFrame() {
replacementFrameBudgetSeconds_ = baseValue / fps;
if ((DebugOverlay)g_Config.iDebugOverlay == DebugOverlay::DEBUG_STATS) {
gpuStats.numReplacerTrackedTex = replacer_.GetNumTrackedTextures();
gpuStats.numCachedReplacedTextures = replacer_.GetNumCachedReplacedTextures();
gpuStats.perFrame.numReplacerTrackedTex = replacer_.GetNumTrackedTextures();
gpuStats.perFrame.numCachedReplacedTextures = replacer_.GetNumCachedReplacedTextures();
}
if (texelsScaledThisFrame_) {
@@ -511,8 +511,8 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
}
if (match) {
if (entry->lastFrame != gpuStats.numFlips) {
u32 diff = gpuStats.numFlips - entry->lastFrame;
if (entry->lastFrame != gpuStats.totals.numFlips) {
u32 diff = gpuStats.totals.numFlips - entry->lastFrame;
entry->numFrames++;
if (entry->framesUntilNextFullHash < diff) {
@@ -710,7 +710,7 @@ TexCacheEntry *TextureCacheCommon::SetTexture() {
}
bool TextureCacheCommon::GetBestFramebufferCandidate(const TextureDefinition &entry, u32 texAddrOffset, AttachCandidate *bestCandidate, const char *context) const {
gpuStats.numFramebufferEvaluations++;
gpuStats.perFrame.numFramebufferEvaluations++;
TinySet<AttachCandidate, 6> candidates;
@@ -831,7 +831,7 @@ void TextureCacheCommon::Decimate(TexCacheEntry *exceptThisOne, bool forcePressu
}
bool hasClut = (iter->second->status & TexCacheEntry::STATUS_CLUT_VARIANTS) != 0;
int killAge = hasClut ? TEXTURE_KILL_AGE_CLUT : killAgeBase;
if (iter->second->lastFrame + killAge < gpuStats.numFlips) {
if (iter->second->lastFrame + killAge < gpuStats.totals.numFlips) {
DeleteTexture(iter++);
} else {
++iter;
@@ -851,7 +851,7 @@ void TextureCacheCommon::Decimate(TexCacheEntry *exceptThisOne, bool forcePressu
continue;
}
// In low memory mode, we kill them all since secondary cache is disabled.
if (lowMemoryMode_ || iter->second->lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.numFlips) {
if (lowMemoryMode_ || iter->second->lastFrame + TEXTURE_SECOND_KILL_AGE < gpuStats.totals.numFlips) {
ReleaseTexture(iter->second.get(), true);
secondCacheSizeEstimate_ -= EstimateTexMemoryUsage(iter->second.get());
iter = secondCache_.erase(iter);
@@ -869,7 +869,7 @@ void TextureCacheCommon::Decimate(TexCacheEntry *exceptThisOne, bool forcePressu
void TextureCacheCommon::DecimateVideos() {
for (auto iter = videos_.begin(); iter != videos_.end(); ) {
if (iter->flips + VIDEO_DECIMATE_AGE < gpuStats.numFlips) {
if (iter->flips + VIDEO_DECIMATE_AGE < gpuStats.totals.numFlips) {
iter = videos_.erase(iter);
} else {
++iter;
@@ -893,7 +893,7 @@ bool TextureCacheCommon::IsVideo(u32 texaddr) const {
void TextureCacheCommon::HandleTextureChange(TexCacheEntry *const entry, const char *reason, bool initialMatch, bool doDelete) {
cacheSizeEstimate_ -= EstimateTexMemoryUsage(entry);
entry->numInvalidated++;
gpuStats.numTextureInvalidations++;
gpuStats.perFrame.numTextureInvalidations++;
DEBUG_LOG(Log::G3D, "Texture different or overwritten, reloading at %08x: %s", entry->addr, reason);
if (doDelete) {
ForgetLastTexture();
@@ -956,7 +956,7 @@ void TextureCacheCommon::NotifyFramebuffer(VirtualFramebuffer *framebuffer, Fram
// Color - no need to look in the mirrors.
for (auto it = cache_.lower_bound(cacheKey), end = cache_.upper_bound(cacheKeyEnd); it != end; ++it) {
it->second->status |= TexCacheEntry::STATUS_FRAMEBUFFER_OVERLAP;
gpuStats.numTextureInvalidationsByFramebuffer++;
gpuStats.perFrame.numTextureInvalidationsByFramebuffer++;
}
if (z_stride != 0) {
@@ -966,11 +966,11 @@ void TextureCacheCommon::NotifyFramebuffer(VirtualFramebuffer *framebuffer, Fram
cacheKeyEnd = (u64)z_endAddr << 32;
for (auto it = cache_.lower_bound(cacheKey | 0x200000), end = cache_.upper_bound(cacheKeyEnd | 0x200000); it != end; ++it) {
it->second->status |= TexCacheEntry::STATUS_FRAMEBUFFER_OVERLAP;
gpuStats.numTextureInvalidationsByFramebuffer++;
gpuStats.perFrame.numTextureInvalidationsByFramebuffer++;
}
for (auto it = cache_.lower_bound(cacheKey | 0x600000), end = cache_.upper_bound(cacheKeyEnd | 0x600000); it != end; ++it) {
it->second->status |= TexCacheEntry::STATUS_FRAMEBUFFER_OVERLAP;
gpuStats.numTextureInvalidationsByFramebuffer++;
gpuStats.perFrame.numTextureInvalidationsByFramebuffer++;
}
}
break;
@@ -1179,7 +1179,7 @@ void TextureCacheCommon::SetTextureFramebuffer(const AttachCandidate &candidate)
framebuffer->usageFlags |= FB_USAGE_TEXTURE;
// Keep the framebuffer alive.
framebuffer->last_frame_used = gpuStats.numFlips;
framebuffer->last_frame_used = gpuStats.totals.numFlips;
nextFramebufferTextureChannel_ = RASTER_COLOR;
@@ -1335,7 +1335,7 @@ void TextureCacheCommon::NotifyConfigChanged() {
void TextureCacheCommon::NotifyWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat fmt) {
addr &= 0x3FFFFFFF;
videos_.push_back({ addr, (u32)size, gpuStats.numFlips });
videos_.push_back({ addr, (u32)size, gpuStats.totals.numFlips });
}
void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes, GPURecord::Recorder *recorder) {
@@ -1394,14 +1394,14 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes, GPURecord::Record
// the framebuffer with the smallest offset. This is yet another framebuffer matching
// loop with its own rules, eventually we'll probably want to do something
// more systematic.
bool okAge = !PSP_CoreParameter().compat.flags().LoadCLUTFromCurrentFrameOnly || framebuffer->last_frame_render == gpuStats.numFlips; // Here we can try heuristics.
bool okAge = !PSP_CoreParameter().compat.flags().LoadCLUTFromCurrentFrameOnly || framebuffer->last_frame_render == gpuStats.totals.numFlips; // Here we can try heuristics.
if (matchRange && !inMargin && offset < (int)clutRenderOffset_) {
if (okAge) {
WARN_LOG_N_TIMES(clutfb, 5, Log::G3D, "Detected LoadCLUT(%d bytes) from framebuffer %08x (%s), last render %d frames ago, byte offset %d, pixel offset %d",
loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), gpuStats.numFlips - framebuffer->last_frame_render, offset, offset / fb_bpp);
framebuffer->last_frame_clut = gpuStats.numFlips;
loadBytes, fb_address, GeBufferFormatToString(framebuffer->fb_format), gpuStats.totals.numFlips - framebuffer->last_frame_render, offset, offset / fb_bpp);
framebuffer->last_frame_clut = gpuStats.totals.numFlips;
// Also mark used so it's not decimated.
framebuffer->last_frame_used = gpuStats.numFlips;
framebuffer->last_frame_used = gpuStats.totals.numFlips;
framebuffer->usageFlags |= FB_USAGE_CLUT;
bestClutAddress = framebuffer->fb_address;
clutRenderOffset_ = (u32)offset;
@@ -1411,7 +1411,7 @@ void TextureCacheCommon::LoadClut(u32 clutAddr, u32 loadBytes, GPURecord::Record
break;
}
} else {
WARN_LOG(Log::G3D, "Ignoring CLUT load from %d frames old buffer at %08x", gpuStats.numFlips - framebuffer->last_frame_render, fb_address);
WARN_LOG(Log::G3D, "Ignoring CLUT load from %d frames old buffer at %08x", gpuStats.totals.numFlips - framebuffer->last_frame_render, fb_address);
}
}
}
@@ -2203,13 +2203,13 @@ void TextureCacheCommon::ApplyTexture(bool doBind) {
if (entry->status & TexCacheEntry::STATUS_CLUT_GPU) {
// Special process.
ApplyTextureDepal(entry);
entry->lastFrame = gpuStats.numFlips;
entry->lastFrame = gpuStats.totals.numFlips;
gstate_c.SetTextureFullAlpha(false);
gstate_c.SetTextureIs3D(false);
gstate_c.SetTextureIsArray(false);
gstate_c.SetTextureIsBGRA(false);
} else {
entry->lastFrame = gpuStats.numFlips;
entry->lastFrame = gpuStats.totals.numFlips;
if (doBind) {
BindTexture(entry);
}
@@ -2419,7 +2419,7 @@ void TextureCacheCommon::ApplyTextureFramebuffer(VirtualFramebuffer *framebuffer
draw2D_->Blit(textureShader, u1, v1, u2, v2, u1, v1, u2, v2, framebuffer->renderWidth, framebuffer->renderHeight, depalWidth, framebuffer->renderHeight, false, framebuffer->renderScaleFactor);
gpuStats.numDepal++;
gpuStats.perFrame.numDepal++;
gstate_c.curTextureWidth = texWidth;
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
@@ -2521,7 +2521,7 @@ void TextureCacheCommon::ApplyTextureDepal(TexCacheEntry *entry) {
draw2D_->Blit(textureShader, u1, v1, u2, v2, u1, v1, u2, v2, texWidth, texHeight, texWidth, texHeight, false, 1);
gpuStats.numDepal++;
gpuStats.perFrame.numDepal++;
gstate_c.curTextureWidth = texWidth;
gstate_c.Dirty(DIRTY_UVSCALEOFFSET);
@@ -2718,11 +2718,11 @@ void TextureCacheCommon::Invalidate(u32 addr, int size, GPUInvalidationType type
entry->minihash = (entry->minihash ^ 0x89ABCDEF) + 89;
}
if (type != GPU_INVALIDATE_ALL) {
gpuStats.numTextureInvalidations++;
gpuStats.perFrame.numTextureInvalidations++;
// Start it over from 0 (unless it's safe.)
entry->numFrames = type == GPU_INVALIDATE_SAFE ? 256 : 0;
if (type == GPU_INVALIDATE_SAFE) {
u32 diff = gpuStats.numFlips - entry->lastFrame;
u32 diff = gpuStats.totals.numFlips - entry->lastFrame;
// We still need to mark if the texture is frequently changing, even if it's safely changing.
if (diff < TEXCACHE_FRAME_CHANGE_FREQUENT) {
entry->status |= TexCacheEntry::STATUS_CHANGE_FREQUENT;
@@ -2770,7 +2770,7 @@ std::string AttachCandidate::ToString() const {
}
bool TextureCacheCommon::PrepareBuildTexture(BuildTexturePlan &plan, TexCacheEntry *entry) {
gpuStats.numTexturesDecoded++;
gpuStats.perFrame.numTexturesDecoded++;
// For the estimate, we assume cluts always point to 8888 for simplicity.
cacheSizeEstimate_ += EstimateTexMemoryUsage(entry);
+1 -1
View File
@@ -485,7 +485,7 @@ protected:
}
const u32 *checkp = (const u32 *)Memory::GetPointer(addr);
gpuStats.numTextureDataBytesHashed += sizeInRAM;
gpuStats.perFrame.numTextureDataBytesHashed += sizeInRAM;
if (Memory::IsValidAddress(addr + sizeInRAM)) {
return StableQuickTexHash(checkp, sizeInRAM);
+4 -4
View File
@@ -59,7 +59,7 @@ ClutTexture TextureShaderCache::GetClutTexture(GEPaletteFormat clutFormat, const
auto oldtex = texCache_.find(clutId);
if (oldtex != texCache_.end()) {
oldtex->second->lastFrame = gpuStats.numFlips;
oldtex->second->lastFrame = gpuStats.totals.numFlips;
return *oldtex->second;
}
@@ -132,7 +132,7 @@ ClutTexture TextureShaderCache::GetClutTexture(GEPaletteFormat clutFormat, const
}
tex->texture = draw_->CreateTexture(desc);
tex->lastFrame = gpuStats.numFlips;
tex->lastFrame = gpuStats.totals.numFlips;
texCache_[clutId] = tex;
return *tex;
@@ -187,7 +187,7 @@ Draw::SamplerState *TextureShaderCache::GetSampler(bool linearFilter) {
void TextureShaderCache::Decimate() {
for (auto tex = texCache_.begin(); tex != texCache_.end(); ) {
if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.numFlips) {
if (tex->second->lastFrame + DEPAL_TEXTURE_OLD_AGE < gpuStats.totals.numFlips) {
tex->second->texture->Release();
delete tex->second;
texCache_.erase(tex++);
@@ -195,7 +195,7 @@ void TextureShaderCache::Decimate() {
++tex;
}
}
gpuStats.numClutTextures = (int)texCache_.size();
gpuStats.perFrame.numClutTextures = (int)texCache_.size();
}
Draw2DPipeline *TextureShaderCache::GetDepalettizeShader(uint32_t clutMode, GETextureFormat textureFormat, GEBufferFormat bufferFormat, bool smoothedDepal, u32 depthUpperBits) {
+2 -2
View File
@@ -304,7 +304,7 @@ void DrawEngineD3D11::Flush() {
bool useElements;
DecodeVerts(dec_, decoded_);
DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false);
gpuStats.numUncachedVertsDrawn += vertexCount;
gpuStats.perFrame.numUncachedVertsDrawn += vertexCount;
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
if (gstate.isModeThrough()) {
@@ -392,7 +392,7 @@ void DrawEngineD3D11::Flush() {
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
}
gpuStats.numUncachedVertsDrawn += vertexCount;
gpuStats.perFrame.numUncachedVertsDrawn += vertexCount;
prim = IndexGenerator::GeneralPrim((GEPrimitiveType)drawInds_[0].prim);
VERBOSE_LOG(Log::G3D, "Flush prim %i SW! %i verts in one go", prim, vertexCount);
+4 -8
View File
@@ -20,6 +20,7 @@
#include "Common/Log.h"
#include "Common/GraphicsContext.h"
#include "Common/Profiler/Profiler.h"
#include "Common/Data/Text/StringWriter.h"
#include "GPU/GPUState.h"
@@ -140,14 +141,9 @@ void GPU_D3D11::FinishDeferred() {
drawEngine_.FinishDeferred();
}
void GPU_D3D11::GetStats(char *buffer, size_t bufsize) {
size_t offset = FormatGPUStatsCommon(buffer, bufsize);
buffer += offset;
bufsize -= offset;
if ((int)bufsize < 0)
return;
snprintf(buffer, bufsize,
"Vertex, Fragment shaders loaded: %d, %d\n",
void GPU_D3D11::GetStats(StringWriter &w) {
FormatGPUStatsCommon(w);
w.F("Vertex, Fragment shaders loaded: %d, %d\n",
shaderManagerD3D11_->GetNumVertexShaders(),
shaderManagerD3D11_->GetNumFragmentShaders()
);
+2 -1
View File
@@ -28,6 +28,7 @@
class FramebufferManagerD3D11;
class ShaderManagerD3D11;
class TextureCacheD3D11;
class StringWriter;
class GPU_D3D11 : public GPUCommonHW {
public:
@@ -36,7 +37,7 @@ public:
u32 CheckGPUFeatures() const override;
void GetStats(char *buffer, size_t bufsize) override;
void GetStats(StringWriter &w) override;
void DeviceLost() override; // Destroy all device objects.
void DeviceRestore(Draw::DrawContext *draw) override;
+6 -6
View File
@@ -135,7 +135,7 @@ bool Recorder::BeginRecording() {
nextFrame = false;
lastTextures.clear();
lastRenderTargets.clear();
flipLastAction = gpuStats.numFlips;
flipLastAction = gpuStats.totals.numFlips;
flipFinishAt = -1;
u32 ptr = (u32)pushbuf.size();
@@ -575,7 +575,7 @@ void Recorder::EmitBezierSpline(u32 op) {
bool Recorder::RecordNextFrame(const std::function<void(const Path &)> callback) {
if (!nextFrame) {
flipLastAction = gpuStats.numFlips;
flipLastAction = gpuStats.totals.numFlips;
flipFinishAt = -1;
writeCallback = callback;
nextFrame = true;
@@ -597,7 +597,7 @@ void Recorder::FinishRecording() {
NOTICE_LOG(Log::System, "Recording finished");
active = false;
flipLastAction = gpuStats.numFlips;
flipLastAction = gpuStats.totals.numFlips;
flipFinishAt = -1;
lastEdramTrans = 0x400;
@@ -785,9 +785,9 @@ void Recorder::NotifyDisplay(u32 framebuf, int stride, int fmt) {
}
void Recorder::NotifyBeginFrame() {
const bool noDisplayAction = flipLastAction + 4 < gpuStats.numFlips;
const bool noDisplayAction = flipLastAction + 4 < gpuStats.totals.numFlips;
// We do this only to catch things that don't call NotifyDisplay.
if (active && HasDrawCommands() && (noDisplayAction || gpuStats.numFlips == flipFinishAt)) {
if (active && HasDrawCommands() && (noDisplayAction || gpuStats.totals.numFlips == flipFinishAt)) {
NOTICE_LOG(Log::System, "Recording complete on frame");
CheckEdramTrans();
@@ -813,7 +813,7 @@ void Recorder::NotifyBeginFrame() {
NOTICE_LOG(Log::System, "Recording starting on frame...");
BeginRecording();
// If we began on a BeginFrame, end on a BeginFrame.
flipFinishAt = gpuStats.numFlips + 1;
flipFinishAt = gpuStats.totals.numFlips + 1;
}
}
+1 -1
View File
@@ -337,7 +337,7 @@ void DrawEngineGLES::Flush() {
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
}
gpuStats.numUncachedVertsDrawn += vertexCount;
gpuStats.perFrame.numUncachedVertsDrawn += vertexCount;
prim = IndexGenerator::GeneralPrim((GEPrimitiveType)drawInds_[0].prim);
// We need correct viewport values in gstate_c already.
+3 -3
View File
@@ -48,7 +48,7 @@ void FragmentTestCacheGLES::BindTestTexture(int slot) {
const FragmentTestID id = GenerateTestID();
const auto cached = cache_.find(id);
if (cached != cache_.end()) {
cached->second.lastFrame = gpuStats.numFlips;
cached->second.lastFrame = gpuStats.totals.numFlips;
GLRTexture *tex = cached->second.texture;
if (tex == lastTexture_) {
// Already bound, hurray.
@@ -78,7 +78,7 @@ void FragmentTestCacheGLES::BindTestTexture(int slot) {
// We only need to do this once for the texture.
render_->SetTextureSampler(slot, GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE, GL_NEAREST, GL_NEAREST, 0.0f);
FragmentTestTexture item;
item.lastFrame = gpuStats.numFlips;
item.lastFrame = gpuStats.totals.numFlips;
item.texture = tex;
cache_[id] = item;
}
@@ -156,7 +156,7 @@ void FragmentTestCacheGLES::Clear(bool deleteThem) {
void FragmentTestCacheGLES::Decimate() {
if (--decimationCounter_ <= 0) {
for (auto tex = cache_.begin(); tex != cache_.end(); ) {
if (tex->second.lastFrame + FRAGTEST_TEXTURE_OLD_AGE < gpuStats.numFlips) {
if (tex->second.lastFrame + FRAGTEST_TEXTURE_OLD_AGE < gpuStats.totals.numFlips) {
render_->DeleteTexture(tex->second.texture);
cache_.erase(tex++);
} else {
+5 -9
View File
@@ -21,6 +21,7 @@
#include "Common/Log.h"
#include "Common/Serialize/Serializer.h"
#include "Common/File/FileUtil.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/GraphicsContext.h"
#include "Common/System/OSD.h"
#include "Common/VR/PPSSPPVR.h"
@@ -248,7 +249,7 @@ void GPU_GLES::BeginHostFrame(const DisplayLayoutConfig &config) {
// Save the cache from time to time. TODO: How often? We save on exit, so shouldn't need to do this all that often.
constexpr int saveShaderCacheFrameInterval = 32767; // power of 2 - 1. About every 10 minutes at 60fps.
if (shaderCachePath_.Valid() && !(gpuStats.numFlips & saveShaderCacheFrameInterval) && coreState == CORE_RUNNING_CPU) {
if (shaderCachePath_.Valid() && !(gpuStats.totals.numFlips & saveShaderCacheFrameInterval) && coreState == CORE_RUNNING_CPU) {
shaderManagerGL_->SaveCache(shaderCachePath_, &drawEngine_);
}
shaderManagerGL_->DirtyLastShader();
@@ -278,16 +279,11 @@ void GPU_GLES::FinishDeferred() {
drawEngine_.FinishDeferred();
}
void GPU_GLES::GetStats(char *buffer, size_t bufsize) {
size_t offset = FormatGPUStatsCommon(buffer, bufsize);
buffer += offset;
bufsize -= offset;
if ((int)bufsize < 0)
return;
snprintf(buffer, bufsize,
"Vertex, Fragment, Programs loaded: %d, %d, %d\n",
void GPU_GLES::GetStats(StringWriter &w) {
w.F("Vertex, Fragment, Programs loaded: %d, %d, %d\n",
shaderManagerGL_->GetNumVertexShaders(),
shaderManagerGL_->GetNumFragmentShaders(),
shaderManagerGL_->GetNumPrograms()
);
FormatGPUStatsCommon(w);
}
+1 -1
View File
@@ -39,7 +39,7 @@ public:
// This gets called on startup and when we get back from settings.
u32 CheckGPUFeatures() const override;
void GetStats(char *buffer, size_t bufsize) override;
void GetStats(StringWriter &w) override;
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
void DeviceRestore(Draw::DrawContext *draw) override;
+21 -56
View File
@@ -68,61 +68,8 @@ inline unsigned int toFloat24(float f) {
return i >> 8;
}
// The ToString function lives in GPUCommonHW.cpp.
struct GPUStatistics {
void Reset() {
ResetFrame();
numFlips = 0;
}
void ResetFrame() {
numDrawCalls = 0;
numVertexDecodes = 0;
numCulledDraws = 0;
numDrawSyncs = 0;
numListSyncs = 0;
numVertsSubmitted = 0;
numVertsDecoded = 0;
numUncachedVertsDrawn = 0;
numTextureInvalidations = 0;
numTextureInvalidationsByFramebuffer = 0;
numTexturesHashed = 0;
numTextureDataBytesHashed = 0;
numFlushes = 0;
numBBOXJumps = 0;
numTexturesDecoded = 0;
numFramebufferEvaluations = 0;
numFBOsCreated = 0;
numBlockingReadbacks = 0;
numReadbacks = 0;
numUploads = 0;
numCachedUploads = 0;
numDepal = 0;
numClears = 0;
numDepthCopies = 0;
numReinterpretCopies = 0;
numColorCopies = 0;
numCopiesForShaderBlend = 0;
numCopiesForSelfTex = 0;
numBlockTransfers = 0;
numReplacerTrackedTex = 0;
numCachedReplacedTextures = 0;
numClutTextures = 0;
msProcessingDisplayLists = 0;
msPrepareDepth = 0.0;
msCullDepth = 0.0;
msRasterizeDepth = 0.0;
msRasterTimeAvailable = 0.0;
numDepthRasterPrims = 0;
numDepthRasterEarlySize = 0;
numDepthRasterNoPixels = 0;
numDepthRasterTooSmall = 0;
numDepthRasterZCulled = 0;
numDepthEarlyBoxCulled = 0;
vertexGPUCycles = 0;
otherGPUCycles = 0;
}
// TODO: Possibly use macros to disable expensive parts of stats tracking in release builds.
struct GPUStatsPerFrame {
// Per frame statistics
int numDrawCalls;
int numVertexDecodes;
@@ -169,10 +116,28 @@ struct GPUStatistics {
int numDepthRasterTooSmall;
int numDepthRasterZCulled;
int numDepthEarlyBoxCulled;
// Flip count. Doesn't really belong here.
};
struct GPUStatsTotals {
int numFlips;
};
// The ToString function lives in GPUCommonHW.cpp.
struct GPUStatistics {
void Reset() {
ResetFrame();
totals = {};
}
void ResetFrame() {
perFrame = {};
}
// Flip count. Doesn't really belong here.
GPUStatsPerFrame perFrame;
GPUStatsTotals totals;
};
extern GPUStatistics gpuStats;
extern GPUCommon *gpu;
extern GPUDebugInterface *gpuDebug;
+10 -10
View File
@@ -55,7 +55,7 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) :
Reinitialize();
gstate.Reset();
gstate_c.Reset();
gpuStats.Reset();
gpuStats.ResetFrame();
PPGeSetDrawContext(draw);
ResetMatrices();
@@ -172,7 +172,7 @@ void GPUCommon::DumpNextFrame() {
}
u32 GPUCommon::DrawSync(int mode) {
gpuStats.numDrawSyncs++;
gpuStats.perFrame.numDrawSyncs++;
if (mode < 0 || mode > 1)
return SCE_KERNEL_ERROR_INVALID_MODE;
@@ -222,7 +222,7 @@ void GPUCommon::CheckDrawSync() {
}
int GPUCommon::ListSync(int listid, int mode) {
gpuStats.numListSyncs++;
gpuStats.perFrame.numListSyncs++;
if (listid < 0 || listid >= DisplayListMaxCount)
return SCE_KERNEL_ERROR_INVALID_ID;
@@ -737,7 +737,7 @@ DLResult GPUCommon::ProcessDLQueue() {
}
}
TimeCollector collectStat(&gpuStats.msProcessingDisplayLists, coreCollectDebugStats);
TimeCollector collectStat(&gpuStats.perFrame.msProcessingDisplayLists, coreCollectDebugStats);
auto GetNextListIndex = [&]() -> int {
if (dlQueue.empty())
@@ -866,7 +866,7 @@ DLResult GPUCommon::ProcessDLQueue() {
currentList = nullptr;
if (coreCollectDebugStats) {
gpuStats.otherGPUCycles += cyclesExecuted;
gpuStats.perFrame.otherGPUCycles += cyclesExecuted;
}
drawCompleteTicks = startingTicks + cyclesExecuted;
@@ -915,7 +915,7 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) {
if (!currentList->bboxResult) {
// bounding box jump.
const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC);
gpuStats.numBBOXJumps++;
gpuStats.perFrame.numBBOXJumps++;
if (Memory::IsValidAddress(target)) {
UpdatePC(currentList->pc, target - 4);
currentList->pc = target - 4; // pc will be increased after we return, counteract that
@@ -1400,7 +1400,7 @@ void GPUCommon::FastLoadBoneMatrix(u32 target) {
cyclesExecuted += 2 * 14; // one to reset the counter, 12 to load the matrix, and a return.
if (coreCollectDebugStats) {
gpuStats.otherGPUCycles += 2 * 14;
gpuStats.perFrame.otherGPUCycles += 2 * 14;
}
}
@@ -1720,7 +1720,7 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) {
int bpp = gstate.getTransferBpp();
DEBUG_LOG(Log::G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY);
gpuStats.numBlockTransfers++;
gpuStats.perFrame.numBlockTransfers++;
// For VRAM, we wrap around when outside valid memory (mirrors still work.)
if ((srcBasePtr & 0x04800000) == 0x04800000)
@@ -2090,10 +2090,10 @@ GPUDebug::NotifyResult GPUCommon::NotifyCommand(u32 pc, GPUBreakpoints *breakpoi
u32 op = Memory::ReadUnchecked_U32(pc);
u32 cmd = op >> 24;
if (thisFlipNum_ != gpuStats.numFlips) {
if (thisFlipNum_ != gpuStats.totals.numFlips) {
primsLastFrame_ = primsThisFrame_;
primsThisFrame_ = 0;
thisFlipNum_ = gpuStats.numFlips;
thisFlipNum_ = gpuStats.totals.numFlips;
}
bool isPrim = false;
+55 -54
View File
@@ -3,6 +3,7 @@
#include "Common/GPU/thin3d.h"
#include "Common/Serialize/Serializer.h"
#include "Common/System/System.h"
#include "Common/Data/Text/StringWriter.h"
#include "Core/System.h"
#include "Core/Config.h"
@@ -770,9 +771,9 @@ void GPUCommonHW::CheckDepthUsage(VirtualFramebuffer *vfb) {
if (isWritingDepth || isReadingDepth) {
gstate_c.usingDepth = true;
gstate_c.clearingDepth = isClearingDepth;
vfb->last_frame_depth_render = gpuStats.numFlips;
vfb->last_frame_depth_render = gpuStats.totals.numFlips;
if (isWritingDepth) {
vfb->last_frame_depth_updated = gpuStats.numFlips;
vfb->last_frame_depth_updated = gpuStats.totals.numFlips;
}
framebufferManager_->SetDepthFrameBuffer(isClearingDepth);
}
@@ -980,7 +981,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
// Rough estimate, not sure what's correct.
cyclesExecuted += vertexCost_ * count;
if (gstate.isModeClear()) {
gpuStats.numClears++;
gpuStats.perFrame.numClears++;
}
return;
}
@@ -1027,9 +1028,9 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
if ((vertexType & (GE_VTYPE_THROUGH_MASK | GE_VTYPE_POS_MASK | GE_VTYPE_IDX_MASK)) == (GE_VTYPE_THROUGH_MASK | GE_VTYPE_POS_FLOAT | GE_VTYPE_IDX_NONE)) {
int bytesRead = 0;
if (!drawEngineCommon_->TestBoundingBoxThrough(verts, count, decoder, vertexType, &bytesRead)) {
gpuStats.numCulledDraws++;
gpuStats.perFrame.numCulledDraws++;
int cycles = vertexCost_ * count;
gpuStats.vertexGPUCycles += cycles;
gpuStats.perFrame.vertexGPUCycles += cycles;
cyclesExecuted += cycles;
// NOTE! We still have to advance vertex pointers!
gstate_c.vertexAddr += bytesRead; // We know from the above check that it's not an indexed draw.
@@ -1057,7 +1058,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
if (drawEngineCommon_->TestBoundingBoxFast(gstate_c.worldviewproj, verts, count, decoder, vertexType)) {
passCulling = true;
} else {
gpuStats.numCulledDraws++;
gpuStats.perFrame.numCulledDraws++;
}
}
@@ -1147,7 +1148,7 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
if (drawEngineCommon_->TestBoundingBoxFast(gstate_c.worldviewproj, verts, count, decoder, vertexType)) {
passCulling = true;
} else {
gpuStats.numCulledDraws++;
gpuStats.perFrame.numCulledDraws++;
}
}
if (passCulling) {
@@ -1301,7 +1302,7 @@ bail:
}
int cycles = vertexCost_ * totalVertCount;
gpuStats.vertexGPUCycles += cycles;
gpuStats.perFrame.vertexGPUCycles += cycles;
if (!PSP_CoreParameter().compat.flags().FastEmulatedGPU) {
cyclesExecuted += cycles;
@@ -1825,9 +1826,9 @@ int GPUCommonHW::ListSync(int listid, int mode) {
return GPUCommon::ListSync(listid, mode);
}
size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
float vertexAverageCycles = gpuStats.numVertsSubmitted > 0 ? (float)gpuStats.vertexGPUCycles / (float)gpuStats.numVertsSubmitted : 0.0f;
return snprintf(buffer, size,
void GPUCommonHW::FormatGPUStatsCommon(StringWriter &w) {
float vertexAverageCycles = gpuStats.perFrame.numVertsSubmitted > 0 ? (float)gpuStats.perFrame.vertexGPUCycles / (float)gpuStats.perFrame.numVertsSubmitted : 0.0f;
w.F(
"DL processing time: %0.2f ms, %d drawsync, %d listsync\n"
"Draw: %d (%d dec, %d culled), flushes %d, clears %d, bbox jumps %d\n"
"Vertices: %d dec: %d drawn: %d\n"
@@ -1840,52 +1841,52 @@ size_t GPUCommonHW::FormatGPUStatsCommon(char *buffer, size_t size) {
"GPU cycles: %d (%0.1f per vertex)\n"
"Z-rast: %0.2f+%0.2f+%0.2f (total %0.2f/%0.2f) ms\n"
"Z-rast: %d prim, %d nopix, %d small, %d earlysize, %d zcull, %d box\n%s",
gpuStats.msProcessingDisplayLists * 1000.0f,
gpuStats.numDrawSyncs,
gpuStats.numListSyncs,
gpuStats.numDrawCalls,
gpuStats.numVertexDecodes,
gpuStats.numCulledDraws,
gpuStats.numFlushes,
gpuStats.numClears,
gpuStats.numBBOXJumps,
gpuStats.numVertsSubmitted,
gpuStats.numVertsDecoded,
gpuStats.numUncachedVertsDrawn,
gpuStats.perFrame.msProcessingDisplayLists * 1000.0f,
gpuStats.perFrame.numDrawSyncs,
gpuStats.perFrame.numListSyncs,
gpuStats.perFrame.numDrawCalls,
gpuStats.perFrame.numVertexDecodes,
gpuStats.perFrame.numCulledDraws,
gpuStats.perFrame.numFlushes,
gpuStats.perFrame.numClears,
gpuStats.perFrame.numBBOXJumps,
gpuStats.perFrame.numVertsSubmitted,
gpuStats.perFrame.numVertsDecoded,
gpuStats.perFrame.numUncachedVertsDrawn,
(int)framebufferManager_->NumVFBs(),
gpuStats.numFramebufferEvaluations,
gpuStats.numFBOsCreated,
gpuStats.perFrame.numFramebufferEvaluations,
gpuStats.perFrame.numFBOsCreated,
(int)textureCache_->NumLoadedTextures(),
gpuStats.numTexturesDecoded,
gpuStats.numTextureInvalidations,
gpuStats.numTextureDataBytesHashed / 1024,
gpuStats.numClutTextures,
gpuStats.numBlockingReadbacks,
gpuStats.numReadbacks,
gpuStats.numUploads,
gpuStats.numCachedUploads,
gpuStats.numDepal,
gpuStats.numBlockTransfers,
gpuStats.numReplacerTrackedTex,
gpuStats.numCachedReplacedTextures,
gpuStats.numDepthCopies,
gpuStats.numColorCopies,
gpuStats.numReinterpretCopies,
gpuStats.numCopiesForShaderBlend,
gpuStats.numCopiesForSelfTex,
gpuStats.vertexGPUCycles + gpuStats.otherGPUCycles,
gpuStats.perFrame.numTexturesDecoded,
gpuStats.perFrame.numTextureInvalidations,
gpuStats.perFrame.numTextureDataBytesHashed / 1024,
gpuStats.perFrame.numClutTextures,
gpuStats.perFrame.numBlockingReadbacks,
gpuStats.perFrame.numReadbacks,
gpuStats.perFrame.numUploads,
gpuStats.perFrame.numCachedUploads,
gpuStats.perFrame.numDepal,
gpuStats.perFrame.numBlockTransfers,
gpuStats.perFrame.numReplacerTrackedTex,
gpuStats.perFrame.numCachedReplacedTextures,
gpuStats.perFrame.numDepthCopies,
gpuStats.perFrame.numColorCopies,
gpuStats.perFrame.numReinterpretCopies,
gpuStats.perFrame.numCopiesForShaderBlend,
gpuStats.perFrame.numCopiesForSelfTex,
gpuStats.perFrame.vertexGPUCycles + gpuStats.perFrame.otherGPUCycles,
vertexAverageCycles,
gpuStats.msPrepareDepth * 1000.0,
gpuStats.msCullDepth * 1000.0,
gpuStats.msRasterizeDepth * 1000.0,
(gpuStats.msPrepareDepth + gpuStats.msCullDepth + gpuStats.msRasterizeDepth) * 1000.0,
gpuStats.msRasterTimeAvailable * 1000.0,
gpuStats.numDepthRasterPrims,
gpuStats.numDepthRasterNoPixels,
gpuStats.numDepthRasterTooSmall,
gpuStats.numDepthRasterEarlySize,
gpuStats.numDepthRasterZCulled,
gpuStats.numDepthEarlyBoxCulled,
gpuStats.perFrame.msPrepareDepth * 1000.0,
gpuStats.perFrame.msCullDepth * 1000.0,
gpuStats.perFrame.msRasterizeDepth * 1000.0,
(gpuStats.perFrame.msPrepareDepth + gpuStats.perFrame.msCullDepth + gpuStats.perFrame.msRasterizeDepth) * 1000.0,
gpuStats.perFrame.msRasterTimeAvailable * 1000.0,
gpuStats.perFrame.numDepthRasterPrims,
gpuStats.perFrame.numDepthRasterNoPixels,
gpuStats.perFrame.numDepthRasterTooSmall,
gpuStats.perFrame.numDepthRasterEarlySize,
gpuStats.perFrame.numDepthRasterZCulled,
gpuStats.perFrame.numDepthEarlyBoxCulled,
debugRecording_ ? "(debug-recording)" : ""
);
}
+3 -1
View File
@@ -2,6 +2,8 @@
#include "GPUCommon.h"
class StringWriter;
// Shared GPUCommon implementation for the HW backends.
// Things that are irrelevant for SoftGPU should live here.
class GPUCommonHW : public GPUCommon {
@@ -88,7 +90,7 @@ private:
void CheckFlushOp(int cmd, u32 diff);
protected:
size_t FormatGPUStatsCommon(char *buf, size_t size);
void FormatGPUStatsCommon(StringWriter &w);
void UpdateCmdInfo() override;
void PreExecuteOp(u32 op, u32 diff) override;
+2
View File
@@ -17,6 +17,8 @@
#pragma once
// Note: GPU statistics are in GPU.h.
#include "ppsspp_config.h"
#include "Common/CommonTypes.h"
+5 -6
View File
@@ -21,6 +21,7 @@
#include "Common/Profiler/Profiler.h"
#include "Common/Thread/ThreadManager.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/TimeUtil.h"
#include "Core/System.h"
#include "GPU/Common/TextureDecoder.h"
@@ -185,8 +186,8 @@ void BinManager::UpdateState() {
ClearDirty(SoftDirty::PIXEL_ALL | SoftDirty::SAMPLER_ALL | SoftDirty::RAST_ALL);
}
if (lastFlipstats_ != gpuStats.numFlips) {
lastFlipstats_ = gpuStats.numFlips;
if (lastFlipstats_ != gpuStats.totals.numFlips) {
lastFlipstats_ = gpuStats.totals.numFlips;
ResetStats();
}
@@ -672,7 +673,7 @@ bool BinManager::HasPendingRead(uint32_t start, uint32_t stride, uint32_t w, uin
return false;
}
void BinManager::GetStats(char *buffer, size_t bufsize) {
void BinManager::GetStats(StringWriter &w) {
double allTotal = 0.0;
double slowestTotalTime = 0.0;
const char *slowestTotalReason = nullptr;
@@ -695,9 +696,7 @@ void BinManager::GetStats(char *buffer, size_t bufsize) {
}
recentTotal += it.second;
}
snprintf(buffer, bufsize,
"Slowest individual flush: %s (%0.4f)\n"
w.F("Slowest individual flush: %s (%0.4f)\n"
"Slowest frame flush: %s (%0.4f)\n"
"Slowest recent flush: %s (%0.4f)\n"
"Total flush time: %0.4f (%05.2f%%, last 2: %05.2f%%)\n"
+2 -1
View File
@@ -182,6 +182,7 @@ struct BinDirtyRange {
void Expand(uint32_t newBase, uint32_t bpp, uint32_t stride, const DrawingCoords &tl, const DrawingCoords &br);
};
class StringWriter;
class BinManager {
public:
BinManager();
@@ -207,7 +208,7 @@ public:
// Assumes you've also checked for a write (writes are partial so are automatically reads.)
bool HasPendingRead(uint32_t start, uint32_t stride, uint32_t w, uint32_t h);
void GetStats(char *buffer, size_t bufsize);
void GetStats(StringWriter &w);
void ResetStats();
void SetDirty(SoftDirty flags) {
+2 -2
View File
@@ -1273,8 +1273,8 @@ u32 SoftGPU::DrawSync(int mode) {
return GPUCommon::DrawSync(mode);
}
void SoftGPU::GetStats(char *buffer, size_t bufsize) {
drawEngine_->transformUnit.GetStats(buffer, bufsize);
void SoftGPU::GetStats(StringWriter &w) {
drawEngine_->transformUnit.GetStats(w);
}
void SoftGPU::InvalidateCache(u32 addr, int size, GPUInvalidationType type)
+1 -1
View File
@@ -139,7 +139,7 @@ public:
void SetCurFramebufferDirty(bool dirty) override {}
void PrepareCopyDisplayToOutput(const DisplayLayoutConfig &config) override;
void CopyDisplayToOutput(const DisplayLayoutConfig &config) override;
void GetStats(char *buffer, size_t bufsize) override;
void GetStats(StringWriter &w) override;
std::vector<const VirtualFramebuffer *> GetFramebufferList() const override { return std::vector<const VirtualFramebuffer *>(); }
void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override;
void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat format) override;
+2 -2
View File
@@ -892,9 +892,9 @@ void TransformUnit::Flush(GPUCommon *common, const char *reason) {
hasDraws_ = false;
}
void TransformUnit::GetStats(char *buffer, size_t bufsize) {
void TransformUnit::GetStats(StringWriter &w) {
// TODO: More stats?
binner_->GetStats(buffer, bufsize);
binner_->GetStats(w);
}
void TransformUnit::FlushIfOverlap(GPUCommon *common, const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h) {
+2 -1
View File
@@ -111,6 +111,7 @@ class VertexReader;
class SoftwareDrawEngine;
class SoftwareVertexReader;
class StringWriter;
class TransformUnit {
public:
@@ -141,7 +142,7 @@ public:
void FlushIfOverlap(GPUCommon *common, const char *reason, bool modifying, uint32_t addr, uint32_t stride, uint32_t w, uint32_t h);
void NotifyClutUpdate(const void *src);
void GetStats(char *buffer, size_t bufsize);
void GetStats(StringWriter &w);
void SetDirty(SoftDirty flags);
SoftDirty GetDirty();
+1 -1
View File
@@ -395,7 +395,7 @@ void DrawEngineVulkan::Flush() {
gstate_c.vertexFullAlpha = gstate_c.vertexFullAlpha && ((hasColor && (gstate.materialupdate & 1)) || gstate.getMaterialAmbientA() == 255) && (!gstate.isLightingEnabled() || gstate.getAmbientA() == 255);
}
gpuStats.numUncachedVertsDrawn += vertexCount;
gpuStats.perFrame.numUncachedVertsDrawn += vertexCount;
prim = IndexGenerator::GeneralPrim((GEPrimitiveType)drawInds_[0].prim);
// At this point, the output is always an indexed triangle/line/point list, no strips/fans.
+7 -15
View File
@@ -25,6 +25,7 @@
#include "Common/File/FileUtil.h"
#include "Common/GraphicsContext.h"
#include "Common/StringUtils.h"
#include "Common/Data/Text/StringWriter.h"
#include "Core/Config.h"
#include "Core/Reporting.h"
@@ -468,26 +469,17 @@ void GPU_Vulkan::DeviceRestore(Draw::DrawContext *draw) {
InitDeviceObjects();
}
void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) {
size_t offset = FormatGPUStatsCommon(buffer, bufsize);
buffer += offset;
bufsize -= offset;
if ((int)bufsize < 0)
return;
void GPU_Vulkan::GetStats(StringWriter &w) {
const DrawEngineVulkanStats &drawStats = drawEngine_.GetStats();
char texStats[256];
textureCacheVulkan_->GetStats(texStats, sizeof(texStats));
snprintf(buffer, bufsize,
"Vertex, Fragment, Pipelines loaded: %i, %i, %i\n"
"Pushbuffer space used: Vtx %d, Idx %d\n"
"%s\n",
w.F("Vertex, Fragment, Pipelines loaded: %i, %i, %i\n"
"Pushbuffer space used: Vtx %d, Idx %d\n",
shaderManagerVulkan_->GetNumVertexShaders(),
shaderManagerVulkan_->GetNumFragmentShaders(),
pipelineManager_->GetNumPipelines(),
drawStats.pushVertexSpaceUsed,
drawStats.pushIndexSpaceUsed,
texStats
);
drawStats.pushIndexSpaceUsed);
textureCacheVulkan_->GetStats(w);
FormatGPUStatsCommon(w);
}
std::vector<std::string> GPU_Vulkan::DebugGetShaderIDs(DebugShaderType type) {
+2 -1
View File
@@ -32,6 +32,7 @@ class FramebufferManagerVulkan;
class ShaderManagerVulkan;
class LinkedShader;
class TextureCacheVulkan;
class StringWriter;
class GPU_Vulkan : public GPUCommonHW {
public:
@@ -47,7 +48,7 @@ public:
void BeginHostFrame(const DisplayLayoutConfig &config) override;
void EndHostFrame() override;
void GetStats(char *buffer, size_t bufsize) override;
void GetStats(StringWriter &w) override;
void DeviceLost() override; // Only happens on Android. Drop all textures and shaders.
void DeviceRestore(Draw::DrawContext *draw) override;
+1 -3
View File
@@ -1111,9 +1111,7 @@ bool TextureCacheVulkan::GetCurrentTextureDebug(GPUDebugBuffer &buffer, int leve
return true;
}
void TextureCacheVulkan::GetStats(char *ptr, size_t size) {
snprintf(ptr, size, "N/A");
}
void TextureCacheVulkan::GetStats(StringWriter &w) {}
std::vector<std::string> TextureCacheVulkan::DebugGetSamplerIDs() const {
return samplerCache_.DebugGetSamplerIDs();
+2 -1
View File
@@ -33,6 +33,7 @@ class DrawEngineVulkan;
class VulkanContext;
class VulkanTexture;
class StringWriter;
class SamplerCache {
public:
@@ -76,7 +77,7 @@ public:
bool GetCurrentTextureDebug(GPUDebugBuffer &buffer, int level, bool *isFramebuffer) override;
void GetStats(char *ptr, size_t size);
void GetStats(StringWriter &w);
std::vector<std::string> DebugGetSamplerIDs() const;
std::string DebugGetSamplerString(const std::string &id, DebugShaderStringType stringType);
+21 -9
View File
@@ -4,7 +4,7 @@
#include "Common/Data/Text/I18n.h"
#include "Common/CPUDetect.h"
#include "Common/StringUtils.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/StringWriter.h"
#include "Core/MIPS/MIPS.h"
#include "Core/HW/Display.h"
@@ -46,9 +46,20 @@ static void DrawDebugStats(UIContext *ctx, const Bounds &bounds) {
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(.7f, .7f);
__DisplayGetDebugStats(statbuf, sizeof(statbuf));
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, left, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
StringWriter w(statbuf, sizeof(statbuf));
w.F("Kernel processing time: %0.2f ms\n"
"Slowest syscall: %s : %0.2f ms\n"
"Most active syscall: %s : %0.2f ms\n",
kernelStats.msInSyscalls * 1000.0f,
kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)",
kernelStats.slowestSyscallTime * 1000.0f,
kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)",
kernelStats.summedSlowestSyscallTime * 1000.0f);
__DisplayGetDebugStats(w);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 11, bounds.y + 31, left, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 10, bounds.y + 30, left, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
ctx->Draw()->SetFontScale(1.0f, 1.0f);
ctx->Flush();
@@ -58,7 +69,7 @@ static void DrawDebugStats(UIContext *ctx, const Bounds &bounds) {
static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) {
FontID ubuntu24("UBUNTU24");
char statbuf[4096] = { 0 };
char statbuf[4096];
System_AudioGetDebugStats(statbuf, sizeof(statbuf));
ctx->Flush();
@@ -82,14 +93,15 @@ static void DrawAudioDebugStats(UIContext *ctx, const Bounds &bounds) {
static void DrawControlDebug(UIContext *ctx, const ControlMapper &mapper, const Bounds &bounds) {
FontID ubuntu24("UBUNTU24");
char statbuf[4096] = { 0 };
mapper.GetDebugString(statbuf, sizeof(statbuf));
char statbuf[2048];
StringWriter w(statbuf, sizeof(statbuf));
mapper.GetDebugString(w);
ctx->Flush();
ctx->BindFontTexture();
ctx->Draw()->SetFontScale(0.5f, 0.5f);
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, statbuf, bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 11, bounds.y + 31, bounds.w - 20, bounds.h - 30, 0xc0000000, FLAG_DYNAMIC_ASCII);
ctx->Draw()->DrawTextRect(ubuntu24, w.as_view(), bounds.x + 10, bounds.y + 30, bounds.w - 20, bounds.h - 30, 0xFFFFFFFF, FLAG_DYNAMIC_ASCII);
ctx->Draw()->SetFontScale(1.0f, 1.0f);
ctx->Flush();
ctx->RebindTexture();
+2 -2
View File
@@ -7,7 +7,7 @@
#include "Common/StringUtils.h"
#include "Common/File/FileUtil.h"
#include "Common/Data/Format/IniFile.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/Log/LogManager.h"
#include "Common/TimeUtil.h"
#include "Core/Config.h"
@@ -2273,7 +2273,7 @@ void DrawHLEModules(ImConfig &config) {
break;
}
}
w.F("%s 0x%08x %d %s", func.name, func.ID, strlen(func.argmask), amask.c_str()).endl();
w.F("%s 0x%08x %d %s", func.name, func.ID, (int)strlen(func.argmask), amask.c_str()).endl();
}
System_CopyStringToClipboard(w.as_view());
delete[] buffer;
+4 -2
View File
@@ -3,6 +3,7 @@
#include "ext/imgui/imgui_extras.h"
#include "ext/imgui/imgui_impl_thin3d.h"
#include "Common/Data/Convert/ColorConv.h"
#include "Common/Data/Text/StringWriter.h"
#include "UI/ImDebugger/ImGe.h"
#include "UI/ImDebugger/ImDebugger.h"
#include "GPU/Common/GPUDebugInterface.h"
@@ -33,7 +34,7 @@ void DrawFramebuffersWindow(ImConfig &cfg, FramebufferManagerCommon *framebuffer
return;
}
ImGui::Text("Cur frame: %d seq: %d", gpuStats.numFlips, framebufferManager->PeekBindSeqCount());
ImGui::Text("Cur frame: %d seq: %d", gpuStats.totals.numFlips, framebufferManager->PeekBindSeqCount());
ImGui::BeginTable("framebuffers", 7);
ImGui::TableSetupColumn("Tag", ImGuiTableColumnFlags_WidthFixed);
@@ -282,7 +283,8 @@ void DrawDebugStatsWindow(ImConfig &cfg) {
return;
}
char statbuf[4096];
__DisplayGetDebugStats(statbuf, sizeof(statbuf));
StringWriter w(statbuf);
__DisplayGetDebugStats(w);
ImGui::TextUnformatted(statbuf);
ImGui::End();
}
+1 -1
View File
@@ -13,7 +13,7 @@
#include "Common/File/AndroidStorage.h"
#include "Common/Audio/AudioBackend.h"
#include "Common/Data/Text/I18n.h"
#include "Common/Data/Text/Parsers.h"
#include "Common/Data/Text/StringWriter.h"
#include "Common/Data/Encoding/Utf8.h"
#include "Common/Render/Text/draw_text.h"
#include "Common/System/Request.h"