mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Just some refactoring of the GPUStatistics struct, and more use of StringWriter
This commit is contained in:
@@ -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
@@ -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.
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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" />
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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...
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#include "Common/Data/Text/StringWriter.h"
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
@@ -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) {
|
||||
|
||||
@@ -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).
|
||||
|
||||
@@ -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
@@ -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
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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()
|
||||
);
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
@@ -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;
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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;
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
// Note: GPU statistics are in GPU.h.
|
||||
|
||||
#include "ppsspp_config.h"
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user