mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Merge pull request #14884 from unknownbrackets/debugger-gpustats
Debugger: Add APIs for GPU stats
This commit is contained in:
commit
d754f95814
@ -1648,6 +1648,8 @@ add_library(${CoreLibName} ${CoreLinkType}
|
||||
Core/Debugger/WebSocket/GPUBufferSubscriber.h
|
||||
Core/Debugger/WebSocket/GPURecordSubscriber.cpp
|
||||
Core/Debugger/WebSocket/GPURecordSubscriber.h
|
||||
Core/Debugger/WebSocket/GPUStatsSubscriber.cpp
|
||||
Core/Debugger/WebSocket/GPUStatsSubscriber.h
|
||||
Core/Debugger/WebSocket/HLESubscriber.cpp
|
||||
Core/Debugger/WebSocket/HLESubscriber.h
|
||||
Core/Debugger/WebSocket/InputBroadcaster.cpp
|
||||
|
@ -519,6 +519,7 @@
|
||||
<ClCompile Include="Debugger\WebSocket\GameSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GPUBufferSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GPURecordSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\GPUStatsSubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\HLESubscriber.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\InputBroadcaster.cpp" />
|
||||
<ClCompile Include="Debugger\WebSocket\InputSubscriber.cpp" />
|
||||
@ -1076,6 +1077,7 @@
|
||||
<ClInclude Include="Debugger\WebSocket\DisasmSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GPUBufferSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GPURecordSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\GPUStatsSubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\HLESubscriber.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\InputBroadcaster.h" />
|
||||
<ClInclude Include="Debugger\WebSocket\InputSubscriber.h" />
|
||||
|
@ -1181,6 +1181,9 @@
|
||||
<ClCompile Include="KeyMapDefaults.cpp">
|
||||
<Filter>Core</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Debugger\WebSocket\GPUStatsSubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ELF\ElfReader.h">
|
||||
@ -1904,6 +1907,9 @@
|
||||
<ClInclude Include="KeyMapDefaults.h">
|
||||
<Filter>Core</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Debugger\WebSocket\GPUStatsSubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="CMakeLists.txt" />
|
||||
|
@ -55,6 +55,7 @@
|
||||
#include "Core/Debugger/WebSocket/GameSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GPUBufferSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GPURecordSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/GPUStatsSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/HLESubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/InputSubscriber.h"
|
||||
#include "Core/Debugger/WebSocket/MemoryInfoSubscriber.h"
|
||||
@ -70,6 +71,7 @@ static const std::vector<SubscriberInit> subscribers({
|
||||
&WebSocketGameInit,
|
||||
&WebSocketGPUBufferInit,
|
||||
&WebSocketGPURecordInit,
|
||||
&WebSocketGPUStatsInit,
|
||||
&WebSocketHLEInit,
|
||||
&WebSocketInputInit,
|
||||
&WebSocketMemoryInfoInit,
|
||||
|
202
Core/Debugger/WebSocket/GPUStatsSubscriber.cpp
Normal file
202
Core/Debugger/WebSocket/GPUStatsSubscriber.cpp
Normal file
@ -0,0 +1,202 @@
|
||||
// Copyright (c) 2021- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
#include "Core/Debugger/WebSocket/GPUStatsSubscriber.h"
|
||||
#include "Core/HLE/sceDisplay.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
struct CollectedStats {
|
||||
float vps;
|
||||
float fps;
|
||||
float actual_fps;
|
||||
char statbuf[4096];
|
||||
std::vector<double> frameTimes;
|
||||
std::vector<double> sleepTimes;
|
||||
int frameTimePos;
|
||||
};
|
||||
|
||||
struct DebuggerGPUStatsEvent {
|
||||
const CollectedStats &s;
|
||||
const std::string &ticket;
|
||||
|
||||
operator std::string() {
|
||||
JsonWriter j;
|
||||
j.begin();
|
||||
j.writeString("event", "gpu.stats.get");
|
||||
if (!ticket.empty())
|
||||
j.writeRaw("ticket", ticket);
|
||||
j.pushDict("fps");
|
||||
j.writeFloat("actual", s.actual_fps);
|
||||
j.writeFloat("target", s.fps);
|
||||
j.pop();
|
||||
j.pushDict("vblanksPerSecond");
|
||||
j.writeFloat("actual", s.vps);
|
||||
j.writeFloat("target", 60.0 / 1.001);
|
||||
j.pop();
|
||||
j.writeString("info", s.statbuf);
|
||||
j.pushDict("timing");
|
||||
j.pushArray("frames");
|
||||
for (double t : s.frameTimes)
|
||||
j.writeFloat(t);
|
||||
j.pop();
|
||||
j.pushArray("sleep");
|
||||
for (double t : s.sleepTimes)
|
||||
j.writeFloat(t);
|
||||
j.pop();
|
||||
j.writeInt("pos", s.frameTimePos);
|
||||
j.pop();
|
||||
j.end();
|
||||
return j.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct WebSocketGPUStatsState : public DebuggerSubscriber {
|
||||
WebSocketGPUStatsState();
|
||||
~WebSocketGPUStatsState() override;
|
||||
void Get(DebuggerRequest &req);
|
||||
void Feed(DebuggerRequest &req);
|
||||
|
||||
void Broadcast(net::WebSocketServer *ws) override;
|
||||
|
||||
static void FlipForwarder(void *thiz);
|
||||
void FlipListener();
|
||||
|
||||
protected:
|
||||
bool forced_ = false;
|
||||
bool sendNext_ = false;
|
||||
bool sendFeed_ = false;
|
||||
|
||||
std::string lastTicket_;
|
||||
std::mutex pendingLock_;
|
||||
std::vector<CollectedStats> pendingStats_;
|
||||
};
|
||||
|
||||
DebuggerSubscriber *WebSocketGPUStatsInit(DebuggerEventHandlerMap &map) {
|
||||
auto p = new WebSocketGPUStatsState();
|
||||
map["gpu.stats.get"] = std::bind(&WebSocketGPUStatsState::Get, p, std::placeholders::_1);
|
||||
map["gpu.stats.feed"] = std::bind(&WebSocketGPUStatsState::Feed, p, std::placeholders::_1);
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
WebSocketGPUStatsState::WebSocketGPUStatsState() {
|
||||
__DisplayListenFlip(&WebSocketGPUStatsState::FlipForwarder, this);
|
||||
}
|
||||
|
||||
WebSocketGPUStatsState::~WebSocketGPUStatsState() {
|
||||
if (forced_)
|
||||
Core_ForceDebugStats(false);
|
||||
__DisplayForgetFlip(&WebSocketGPUStatsState::FlipForwarder, this);
|
||||
}
|
||||
|
||||
void WebSocketGPUStatsState::FlipForwarder(void *thiz) {
|
||||
WebSocketGPUStatsState *p = (WebSocketGPUStatsState *)thiz;
|
||||
p->FlipListener();
|
||||
}
|
||||
|
||||
void WebSocketGPUStatsState::FlipListener() {
|
||||
if (!sendNext_ && !sendFeed_)
|
||||
return;
|
||||
|
||||
// Okay, collect the data (we'll actually send at next Broadcast.)
|
||||
std::lock_guard<std::mutex> guard(pendingLock_);
|
||||
pendingStats_.resize(pendingStats_.size() + 1);
|
||||
CollectedStats &stats = pendingStats_[pendingStats_.size() - 1];
|
||||
|
||||
__DisplayGetFPS(&stats.vps, &stats.fps, &stats.actual_fps);
|
||||
__DisplayGetDebugStats(stats.statbuf, sizeof(stats.statbuf));
|
||||
|
||||
int valid;
|
||||
double *sleepHistory;
|
||||
double *history = __DisplayGetFrameTimes(&valid, &stats.frameTimePos, &sleepHistory);
|
||||
|
||||
stats.frameTimes.resize(valid);
|
||||
stats.sleepTimes.resize(valid);
|
||||
memcpy(&stats.frameTimes[0], history, sizeof(double) * valid);
|
||||
memcpy(&stats.sleepTimes[0], sleepHistory, sizeof(double) * valid);
|
||||
|
||||
sendNext_ = false;
|
||||
}
|
||||
|
||||
// Get next GPU stats (gpu.stats.get)
|
||||
//
|
||||
// No parameters.
|
||||
//
|
||||
// Response (same event name):
|
||||
// - fps: object with "actual" and "target" properties, representing frames per second.
|
||||
// - vblanksPerSecond: object with "actual" and "target" properties, for vblank cycles.
|
||||
// - info: string, representation of backend-dependent statistics.
|
||||
// - timing: object with properties:
|
||||
// - frames: array of numbers, each representing the time taken for a frame.
|
||||
// - sleep: array of numbers, each representing the delay time waiting for next frame.
|
||||
// - pos: number, index of the current frame (not always last.)
|
||||
//
|
||||
// Note: stats are returned after the next flip completes (paused if CPU or GPU in break.)
|
||||
// Note: info and timing may not be accurate if certain settings are disabled.
|
||||
void WebSocketGPUStatsState::Get(DebuggerRequest &req) {
|
||||
if (!PSP_IsInited())
|
||||
return req.Fail("CPU not started");
|
||||
|
||||
std::lock_guard<std::mutex> guard(pendingLock_);
|
||||
sendNext_ = true;
|
||||
|
||||
const JsonNode *value = req.data.get("ticket");
|
||||
lastTicket_ = value ? json_stringify(value) : "";
|
||||
}
|
||||
|
||||
// Setup GPU stats feed (gpu.stats.feed)
|
||||
//
|
||||
// Parameters:
|
||||
// - enable: optional boolean, pass false to stop the feed.
|
||||
//
|
||||
// No immediate response. Events sent each frame (as gpu.stats.get.)
|
||||
//
|
||||
// Note: info and timing will be accurate after the first frame.
|
||||
void WebSocketGPUStatsState::Feed(DebuggerRequest &req) {
|
||||
if (!PSP_IsInited())
|
||||
return req.Fail("CPU not started");
|
||||
bool enable = true;
|
||||
if (!req.ParamBool("enable", &enable, DebuggerParamType::OPTIONAL))
|
||||
return;
|
||||
|
||||
std::lock_guard<std::mutex> guard(pendingLock_);
|
||||
sendFeed_ = enable;
|
||||
if (forced_ != enable) {
|
||||
Core_ForceDebugStats(enable);
|
||||
forced_ = enable;
|
||||
}
|
||||
}
|
||||
|
||||
void WebSocketGPUStatsState::Broadcast(net::WebSocketServer *ws) {
|
||||
std::lock_guard<std::mutex> guard(pendingLock_);
|
||||
if (lastTicket_.empty() && !sendFeed_) {
|
||||
pendingStats_.clear();
|
||||
return;
|
||||
}
|
||||
|
||||
// To be safe, make sure we only send one if we're doing a get.
|
||||
if (!sendFeed_ && pendingStats_.size() > 1)
|
||||
pendingStats_.resize(1);
|
||||
|
||||
for (size_t i = 0; i < pendingStats_.size(); ++i) {
|
||||
ws->Send(DebuggerGPUStatsEvent{ pendingStats_[i], lastTicket_ });
|
||||
lastTicket_.clear();
|
||||
}
|
||||
pendingStats_.clear();
|
||||
}
|
22
Core/Debugger/WebSocket/GPUStatsSubscriber.h
Normal file
22
Core/Debugger/WebSocket/GPUStatsSubscriber.h
Normal file
@ -0,0 +1,22 @@
|
||||
// Copyright (c) 2021- PPSSPP Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0 or later versions.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "Core/Debugger/WebSocket/WebSocketUtils.h"
|
||||
|
||||
DebuggerSubscriber *WebSocketGPUStatsInit(DebuggerEventHandlerMap &map);
|
@ -15,10 +15,11 @@
|
||||
// Official git repository and contact information can be found at
|
||||
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <vector>
|
||||
|
||||
// TODO: Move this somewhere else, cleanup.
|
||||
#ifndef _WIN32
|
||||
@ -130,7 +131,10 @@ std::map<SceUID, int> vblankPausedWaits;
|
||||
// STATE END
|
||||
|
||||
// Called when vblank happens (like an internal interrupt.) Not part of state, should be static.
|
||||
std::vector<VblankCallback> vblankListeners;
|
||||
static std::mutex listenersLock;
|
||||
static std::vector<VblankCallback> vblankListeners;
|
||||
typedef std::pair<FlipCallback, void *> FlipListener;
|
||||
static std::vector<FlipListener> flipListeners;
|
||||
|
||||
// The vblank period is 731.5 us (0.7315 ms)
|
||||
const double vblankMs = 0.7315;
|
||||
@ -343,21 +347,43 @@ void __DisplayDoState(PointerWrap &p) {
|
||||
}
|
||||
|
||||
void __DisplayShutdown() {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
vblankListeners.clear();
|
||||
flipListeners.clear();
|
||||
vblankWaitingThreads.clear();
|
||||
}
|
||||
|
||||
void __DisplayListenVblank(VblankCallback callback) {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
vblankListeners.push_back(callback);
|
||||
}
|
||||
|
||||
static void __DisplayFireVblank() {
|
||||
for (std::vector<VblankCallback>::iterator iter = vblankListeners.begin(), end = vblankListeners.end(); iter != end; ++iter) {
|
||||
VblankCallback cb = *iter;
|
||||
void __DisplayListenFlip(FlipCallback callback, void *userdata) {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
flipListeners.push_back(std::make_pair(callback, userdata));
|
||||
}
|
||||
|
||||
void __DisplayForgetFlip(FlipCallback callback, void *userdata) {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
flipListeners.erase(std::remove_if(flipListeners.begin(), flipListeners.end(), [&](FlipListener item) {
|
||||
return item.first == callback && item.second == userdata;
|
||||
}), flipListeners.end());
|
||||
}
|
||||
|
||||
static void DisplayFireVblank() {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
for (VblankCallback cb : vblankListeners) {
|
||||
cb();
|
||||
}
|
||||
}
|
||||
|
||||
static void DisplayFireFlip() {
|
||||
std::lock_guard<std::mutex> guard(listenersLock);
|
||||
for (auto cb : flipListeners) {
|
||||
cb.first(cb.second);
|
||||
}
|
||||
}
|
||||
|
||||
void __DisplayVblankBeginCallback(SceUID threadID, SceUID prevCallbackId) {
|
||||
SceUID pauseKey = prevCallbackId == 0 ? threadID : prevCallbackId;
|
||||
|
||||
@ -471,7 +497,7 @@ static void CalculateFPS() {
|
||||
}
|
||||
}
|
||||
|
||||
if (g_Config.bDrawFrameGraph) {
|
||||
if (g_Config.bDrawFrameGraph || coreCollectDebugStats) {
|
||||
frameTimeHistory[frameTimeHistoryPos++] = now - lastFrameTimeHistory;
|
||||
lastFrameTimeHistory = now;
|
||||
frameTimeHistoryPos = frameTimeHistoryPos % frameTimeHistorySize;
|
||||
@ -656,7 +682,7 @@ static void DoFrameIdleTiming() {
|
||||
#endif
|
||||
}
|
||||
|
||||
if (g_Config.bDrawFrameGraph) {
|
||||
if (g_Config.bDrawFrameGraph || coreCollectDebugStats) {
|
||||
frameSleepHistory[frameTimeHistoryPos] += time_now_d() - before;
|
||||
}
|
||||
}
|
||||
@ -742,6 +768,7 @@ void __DisplayFlip(int cyclesLate) {
|
||||
if (fbDirty || noRecentFlip || postEffectRequiresFlip) {
|
||||
int frameSleepPos = frameTimeHistoryPos;
|
||||
CalculateFPS();
|
||||
DisplayFireFlip();
|
||||
|
||||
// Let the user know if we're running slow, so they know to adjust settings.
|
||||
// Sometimes users just think the sound emulation is broken.
|
||||
@ -821,7 +848,7 @@ void __DisplayFlip(int cyclesLate) {
|
||||
CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0);
|
||||
numVBlanksSinceFlip = 0;
|
||||
|
||||
if (g_Config.bDrawFrameGraph) {
|
||||
if (g_Config.bDrawFrameGraph || coreCollectDebugStats) {
|
||||
// Track how long we sleep (whether vsync or sleep_ms.)
|
||||
frameSleepHistory[frameSleepPos] += time_now_d() - lastFrameTimeHistory;
|
||||
}
|
||||
@ -848,7 +875,7 @@ void hleLeaveVblank(u64 userdata, int cyclesLate) {
|
||||
CoreTiming::ScheduleEvent(msToCycles(frameMs - vblankMs) - cyclesLate, enterVblankEvent, userdata);
|
||||
|
||||
// Fire the vblank listeners after the vblank completes.
|
||||
__DisplayFireVblank();
|
||||
DisplayFireVblank();
|
||||
}
|
||||
|
||||
void hleLagSync(u64 userdata, int cyclesLate) {
|
||||
@ -886,7 +913,7 @@ void hleLagSync(u64 userdata, int cyclesLate) {
|
||||
const int over = (int)((now - goal) * 1000000);
|
||||
ScheduleLagSync(over - emuOver);
|
||||
|
||||
if (g_Config.bDrawFrameGraph) {
|
||||
if (g_Config.bDrawFrameGraph || coreCollectDebugStats) {
|
||||
frameSleepHistory[frameTimeHistoryPos] += now - before;
|
||||
}
|
||||
}
|
||||
|
@ -25,16 +25,16 @@ void __DisplayShutdown();
|
||||
|
||||
void Register_sceDisplay();
|
||||
|
||||
// will return true once after every end-of-frame.
|
||||
bool __DisplayFrameDone();
|
||||
|
||||
// Get information about the current framebuffer.
|
||||
bool __DisplayGetFramebuf(PSPPointer<u8> *topaddr, u32 *linesize, u32 *pixelFormat, int mode);
|
||||
void __DisplaySetFramebuf(u32 topaddr, int linesize, int pixelformat, int sync);
|
||||
|
||||
typedef void (*VblankCallback)();
|
||||
// Listen for vblank events. Only register during init.
|
||||
// Listen for vblank events.
|
||||
void __DisplayListenVblank(VblankCallback callback);
|
||||
typedef void (*FlipCallback)(void *userdata);
|
||||
void __DisplayListenFlip(FlipCallback callback, void *userdata);
|
||||
void __DisplayForgetFlip(FlipCallback callback, void *userdata);
|
||||
|
||||
void __DisplayGetDebugStats(char stats[], size_t bufsize);
|
||||
void __DisplayGetFPS(float *out_vps, float *out_fps, float *out_actual_fps);
|
||||
|
@ -98,7 +98,7 @@ static std::string loadingReason;
|
||||
bool audioInitialized;
|
||||
|
||||
bool coreCollectDebugStats = false;
|
||||
bool coreCollectDebugStatsForced = false;
|
||||
static int coreCollectDebugStatsCounter = 0;
|
||||
|
||||
// This can be read and written from ANYWHERE.
|
||||
volatile CoreState coreState = CORE_STEPPING;
|
||||
@ -385,8 +385,9 @@ void Core_UpdateState(CoreState newState) {
|
||||
}
|
||||
|
||||
void Core_UpdateDebugStats(bool collectStats) {
|
||||
if (coreCollectDebugStats != collectStats) {
|
||||
coreCollectDebugStats = collectStats;
|
||||
bool newState = collectStats || coreCollectDebugStatsCounter > 0;
|
||||
if (coreCollectDebugStats != newState) {
|
||||
coreCollectDebugStats = newState;
|
||||
mipsr4k.ClearJitCache();
|
||||
}
|
||||
|
||||
@ -394,6 +395,15 @@ void Core_UpdateDebugStats(bool collectStats) {
|
||||
gpuStats.ResetFrame();
|
||||
}
|
||||
|
||||
void Core_ForceDebugStats(bool enable) {
|
||||
if (enable) {
|
||||
coreCollectDebugStatsCounter++;
|
||||
} else {
|
||||
coreCollectDebugStatsCounter--;
|
||||
}
|
||||
_assert_(coreCollectDebugStatsCounter >= 0);
|
||||
}
|
||||
|
||||
bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) {
|
||||
if (pspIsIniting || pspIsQuitting) {
|
||||
return false;
|
||||
|
@ -94,6 +94,8 @@ struct PSP_LoadingLock {
|
||||
|
||||
// Call before PSP_BeginHostFrame() in order to not miss any GPU stats.
|
||||
void Core_UpdateDebugStats(bool collectStats);
|
||||
// Increments or decrements an internal counter. Intended to be used by debuggers.
|
||||
void Core_ForceDebugStats(bool enable);
|
||||
|
||||
void Audio_Init();
|
||||
void Audio_Shutdown();
|
||||
|
@ -400,6 +400,7 @@
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GameSubscriber.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GPUBufferSubscriber.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GPURecordSubscriber.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GPUStatsSubscriber.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\HLESubscriber.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\InputBroadcaster.h" />
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\InputSubscriber.h" />
|
||||
@ -634,6 +635,7 @@
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GameSubscriber.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GPUBufferSubscriber.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GPURecordSubscriber.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GPUStatsSubscriber.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\HLESubscriber.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\InputBroadcaster.cpp" />
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\InputSubscriber.cpp" />
|
||||
|
@ -682,6 +682,9 @@
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GPURecordSubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\GPUStatsSubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\..\Core\Debugger\WebSocket\HLESubscriber.cpp">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClCompile>
|
||||
@ -1685,6 +1688,9 @@
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GPURecordSubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\GPUStatsSubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\..\Core\Debugger\WebSocket\HLESubscriber.h">
|
||||
<Filter>Debugger\WebSocket</Filter>
|
||||
</ClInclude>
|
||||
|
@ -420,6 +420,7 @@ EXEC_AND_LIB_FILES := \
|
||||
$(SRC)/Core/Debugger/WebSocket/GameSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GPUBufferSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GPURecordSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/GPUStatsSubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/HLESubscriber.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/InputBroadcaster.cpp \
|
||||
$(SRC)/Core/Debugger/WebSocket/InputSubscriber.cpp \
|
||||
|
Loading…
Reference in New Issue
Block a user