Merge pull request #19711 from hrydgard/extracted-commits

Extracted fixes and cleanups from #19709
This commit is contained in:
Henrik Rydgård 2024-12-10 01:27:45 +01:00 committed by GitHub
commit fa40ee7a07
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
13 changed files with 87 additions and 48 deletions

View file

@ -129,6 +129,7 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR
double taken_ms_since_scheduling = (now - scheduleTime) * 1000.0;
double taken_ms = (now - start) * 1000.0;
#ifndef _DEBUG
if (taken_ms < 0.1) {
DEBUG_LOG(Log::G3D, "Pipeline (x/%d) time on %s: %0.2f ms, %0.2f ms since scheduling (fast) rpType: %04x sampleBits: %d (%s)",
countToCompile, GetCurrentThreadName(), taken_ms, taken_ms_since_scheduling, (u32)rpType, (u32)sampleCount, tag_.c_str());
@ -136,6 +137,7 @@ bool VKRGraphicsPipeline::Create(VulkanContext *vulkan, VkRenderPass compatibleR
INFO_LOG(Log::G3D, "Pipeline (x/%d) time on %s: %0.2f ms, %0.2f ms since scheduling rpType: %04x sampleBits: %d (%s)",
countToCompile, GetCurrentThreadName(), taken_ms, taken_ms_since_scheduling, (u32)rpType, (u32)sampleCount, tag_.c_str());
}
#endif
bool success = true;
if (result == VK_INCOMPLETE) {

View file

@ -70,11 +70,13 @@ public:
bool bFirstRun;
bool bGameSpecific = false;
bool bUpdatedInstanceCounter = false;
bool bBrowse; // show a file browser on startup. TODO: Does anyone use this?
int iRunCount; // To be used to for example check for updates every 10 runs and things like that.
// Debugger
bool bAutoRun; // start immediately
bool bBrowse; // when opening the emulator, immediately show a file browser
bool bBreakOnFrameTimeout; // not saved
// General
bool bScreenshotsAsPNG;

View file

@ -90,7 +90,7 @@ static bool g_breakAfterFrame = false;
static MIPSExceptionInfo g_exceptionInfo;
// This is called on EmuThread before RunLoop.
static void Core_ProcessStepping(MIPSDebugInterface *cpu);
static bool Core_ProcessStepping(MIPSDebugInterface *cpu);
void Core_SetGraphicsContext(GraphicsContext *ctx) {
PSP_CoreParameter().graphicsContext = ctx;
@ -173,8 +173,10 @@ void Core_RunLoopUntil(u64 globalticks) {
return;
case CORE_STEPPING_CPU:
case CORE_STEPPING_GE:
Core_ProcessStepping(currentDebugMIPS);
return;
if (Core_ProcessStepping(currentDebugMIPS)) {
return;
}
break;
case CORE_RUNNING_CPU:
mipsr4k.RunLoopUntil(globalticks);
if (g_breakAfterFrame && coreState == CORE_NEXTFRAME) {
@ -327,7 +329,7 @@ static void Core_PerformCPUStep(MIPSDebugInterface *cpu, CPUStepType stepType, i
}
}
static void Core_ProcessStepping(MIPSDebugInterface *cpu) {
static bool Core_ProcessStepping(MIPSDebugInterface *cpu) {
Core_StateProcessed();
// Check if there's any pending save state actions.
@ -336,17 +338,23 @@ static void Core_ProcessStepping(MIPSDebugInterface *cpu) {
switch (coreState) {
case CORE_STEPPING_CPU:
case CORE_STEPPING_GE:
case CORE_RUNNING_GE:
// All good
break;
default:
// Nothing to do.
return;
return true;
}
// Or any GPU actions.
// Legacy stepping code.
GPUStepping::ProcessStepping();
if (coreState == CORE_RUNNING_GE) {
// Retry, to get it done this frame.
return false;
}
// We're not inside jit now, so it's safe to clear the breakpoints.
static int lastSteppingCounter = -1;
if (lastSteppingCounter != steppingCounter) {
@ -360,7 +368,7 @@ static void Core_ProcessStepping(MIPSDebugInterface *cpu) {
std::lock_guard<std::mutex> guard(g_stepMutex);
if (coreState != CORE_STEPPING_CPU || g_cpuStepCommand.empty()) {
return;
return true;
}
Core_ResetException();
@ -377,6 +385,7 @@ static void Core_ProcessStepping(MIPSDebugInterface *cpu) {
// Update disasm dialog.
System_Notify(SystemNotification::MEM_VIEW);
return true;
}
// Free-threaded (hm, possibly except tracing).
@ -430,12 +439,20 @@ void Core_Resume() {
// Should be called from the EmuThread.
bool Core_NextFrame() {
CoreState coreState = ::coreState;
_dbg_assert_(coreState != CORE_STEPPING_GE && coreState != CORE_RUNNING_GE);
if (coreState == CORE_RUNNING_CPU) {
coreState = CORE_NEXTFRAME;
::coreState = CORE_NEXTFRAME;
return true;
} else if (coreState == CORE_STEPPING_CPU) {
// All good, just stepping through so no need to switch to the NextFrame coreState though, that'd
// just lose our stepping state.
INFO_LOG(Log::System, "Reached end-of-frame while stepping the CPU (this is ok)");
return true;
} else {
ERROR_LOG(Log::System, "Core_NextFrame called with wrong core state %s", CoreStateToString(coreState));
return false;
}
}

View file

@ -26,7 +26,7 @@
class GraphicsContext;
// For platforms that don't call Core_Run
// For platforms that don't call Run
void Core_SetGraphicsContext(GraphicsContext *ctx);
// Returns false when an UI exit state is detected.

View file

@ -596,6 +596,7 @@ void PSP_RunLoopWhileState() {
int blockTicks = usToCycles(1000000 / 10);
// Run until CORE_NEXTFRAME
PSP_RunLoopFor(blockTicks);
// TODO: Check for frame timeout?
}
void PSP_RunLoopFor(int cycles) {

View file

@ -1851,9 +1851,9 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, int w,
bool creating = old.bufferWidth == 0;
if (creating) {
WARN_LOG(Log::FrameBuf, "Creating %s FBO at %08x/%08x stride=%d %dx%d (force=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->z_address, vfb->fb_stride, vfb->bufferWidth, vfb->bufferHeight, (int)force);
INFO_LOG(Log::FrameBuf, "Creating %s FBO at %08x/%08x stride=%d %dx%d (force=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->z_address, vfb->fb_stride, vfb->bufferWidth, vfb->bufferHeight, (int)force);
} else {
WARN_LOG(Log::FrameBuf, "Resizing %s FBO at %08x/%08x stride=%d from %dx%d to %dx%d (force=%d, skipCopy=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->z_address, vfb->fb_stride, old.bufferWidth, old.bufferHeight, vfb->bufferWidth, vfb->bufferHeight, (int)force, (int)skipCopy);
INFO_LOG(Log::FrameBuf, "Resizing %s FBO at %08x/%08x stride=%d from %dx%d to %dx%d (force=%d, skipCopy=%d)", GeBufferFormatToString(vfb->fb_format), vfb->fb_address, vfb->z_address, vfb->fb_stride, old.bufferWidth, old.bufferHeight, vfb->bufferWidth, vfb->bufferHeight, (int)force, (int)skipCopy);
}
// During hardware rendering, we always render at full color depth even if the game wouldn't on real hardware.

View file

@ -19,9 +19,11 @@
#include <cstring>
#include <functional>
#include <mutex>
#include <condition_variable>
#include <vector>
#include <snappy-c.h>
#include <zstd.h>
#include "Common/Profiler/Profiler.h"
#include "Common/CommonTypes.h"
#include "Common/Log.h"
@ -100,7 +102,7 @@ protected:
u32 buf_pointer_ = 0;
int last_used_ = 0;
bool Matches(u32 bufpos) {
bool Matches(u32 bufpos) const {
// We check psp_pointer_ because bufpos = 0 is valid, and the initial value.
return buf_pointer_ == bufpos && psp_pointer_ != 0;
}
@ -130,12 +132,12 @@ protected:
u32 buf_pointer_ = 0;
u32 size_ = 0;
bool Matches(u32 bufpos, u32 sz) {
bool Matches(u32 bufpos, u32 sz) const {
// We check psp_pointer_ because bufpos = 0 is valid, and the initial value.
return buf_pointer_ == bufpos && psp_pointer_ != 0 && size_ >= sz;
}
u32 Ptr() {
u32 Ptr() const {
return psp_pointer_;
}
@ -293,7 +295,6 @@ public:
private:
void SyncStall();
bool SubmitCmds(const void *p, u32 sz);
void SubmitListEnd();
void Init(u32 ptr, u32 sz);
@ -331,6 +332,7 @@ private:
void DumpExecute::SyncStall() {
if (execListBuf == 0) {
VERBOSE_LOG(Log::G3D, "SyncStall: No active display list");
return;
}
@ -347,12 +349,11 @@ void DumpExecute::SyncStall() {
currentMIPS->downcount -= listTicks - nowTicks;
}
}
// Make sure downcount doesn't overflow.
CoreTiming::ForceCheck();
}
bool DumpExecute::SubmitCmds(const void *p, u32 sz) {
void DumpExecute::Registers(u32 ptr, u32 sz) {
if (execListBuf == 0) {
u32 allocSize = LIST_BUF_SIZE;
execListBuf = userMemory.Alloc(allocSize, true, "List buf");
@ -361,7 +362,7 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) {
}
if (execListBuf == 0) {
ERROR_LOG(Log::System, "Unable to allocate for display list");
return false;
return;
}
execListPos = execListBuf;
@ -389,13 +390,15 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) {
lastBase_ = execListBuf & 0xFF000000;
// Don't continue until we've stalled.
// TODO: Is this really needed? It seems fine without it.
SyncStall();
}
Memory::MemcpyUnchecked(execListPos, execListQueue.data(), pendingSize);
execListPos += pendingSize;
u32 writePos = execListPos;
Memory::MemcpyUnchecked(execListPos, p, sz);
void *srcData = (void *)(pushbuf_.data() + ptr);
Memory::MemcpyUnchecked(execListPos, srcData, sz);
execListPos += sz;
// TODO: Unfortunate. Maybe Texture commands should contain the bufw instead.
@ -431,8 +434,6 @@ bool DumpExecute::SubmitCmds(const void *p, u32 sz) {
}
execListQueue.clear();
return true;
}
void DumpExecute::SubmitListEnd() {
@ -464,10 +465,6 @@ void DumpExecute::Init(u32 ptr, u32 sz) {
lastBase_ = 0xFFFFFFFF;
}
void DumpExecute::Registers(u32 ptr, u32 sz) {
SubmitCmds(pushbuf_.data() + ptr, sz);
}
void DumpExecute::Vertices(u32 ptr, u32 sz) {
u32 psp = mapping_.Map(ptr, sz, std::bind(&DumpExecute::SyncStall, this));
if (psp == 0) {

View file

@ -97,7 +97,7 @@ void GPUCommon::Reinitialize() {
memset(dls, 0, sizeof(dls));
for (int i = 0; i < DisplayListMaxCount; ++i) {
dls[i].state = PSP_GE_DL_STATE_NONE;
dls[i].waitTicks = 0;
dls[i].waitUntilTicks = 0;
}
nextListID = 0;
@ -273,7 +273,7 @@ int GPUCommon::ListSync(int listid, int mode) {
return SCE_KERNEL_ERROR_ILLEGAL_CONTEXT;
}
if (dl.waitTicks > CoreTiming::GetTicks()) {
if (dl.waitUntilTicks > CoreTiming::GetTicks()) {
__GeWaitCurrentThread(GPU_SYNC_LIST, listid, "GeListSync");
}
return PSP_GE_LIST_COMPLETED;
@ -409,7 +409,7 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
id = possibleID;
break;
}
if (possibleList.state == PSP_GE_DL_STATE_COMPLETED && possibleList.waitTicks < currentTicks) {
if (possibleList.state == PSP_GE_DL_STATE_COMPLETED && possibleList.waitUntilTicks < currentTicks) {
id = possibleID;
}
}
@ -432,7 +432,7 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer<Ps
dl.stackptr = 0;
dl.signal = PSP_GE_SIGNAL_NONE;
dl.interrupted = false;
dl.waitTicks = (u64)-1;
dl.waitUntilTicks = (u64)-1;
dl.interruptsEnabled = interruptsEnabled_;
dl.started = false;
dl.offsetAddr = 0;
@ -489,7 +489,7 @@ u32 GPUCommon::DequeueList(int listid) {
else
dlQueue.remove(listid);
dl.waitTicks = 0;
dl.waitUntilTicks = 0;
__GeTriggerWait(GPU_SYNC_LIST, listid);
CheckDrawSync();
@ -855,7 +855,7 @@ DLResult GPUCommon::ProcessDLQueue() {
for (int listIndex = GetNextListIndex(); listIndex != -1; listIndex = GetNextListIndex()) {
DisplayList &l = dls[listIndex];
DEBUG_LOG(Log::G3D, "Starting DL execution at %08x - stall = %08x (startingTicks=%d)", l.pc, l.stall, startingTicks);
DEBUG_LOG(Log::G3D, "%s DL execution at %08x - stall = %08x (startingTicks=%d)", l.pc == l.startpc ? "Starting" : "Resuming", l.pc, l.stall, startingTicks);
if (!InterpretList(l)) {
switch (gpuState) {
case GPURunState::GPUSTATE_STALL:
@ -1176,9 +1176,9 @@ void GPUCommon::Execute_End(u32 op, u32 diff) {
currentList->pendingInterrupt = true;
} else {
currentList->state = PSP_GE_DL_STATE_COMPLETED;
currentList->waitTicks = startingTicks + cyclesExecuted;
busyTicks = std::max(busyTicks, currentList->waitTicks);
__GeTriggerSync(GPU_SYNC_LIST, currentList->id, currentList->waitTicks);
currentList->waitUntilTicks = startingTicks + cyclesExecuted;
busyTicks = std::max(busyTicks, currentList->waitUntilTicks);
__GeTriggerSync(GPU_SYNC_LIST, currentList->id, currentList->waitUntilTicks);
}
break;
}
@ -1419,7 +1419,7 @@ struct DisplayList_v1 {
DisplayListStackEntry stack[32];
int stackptr;
bool interrupted;
u64 waitTicks;
u64 waitUntilTicks;
bool interruptsEnabled;
bool pendingInterrupt;
bool started;
@ -1440,7 +1440,7 @@ struct DisplayList_v2 {
DisplayListStackEntry stack[32];
int stackptr;
bool interrupted;
u64 waitTicks;
u64 waitUntilTicks;
bool interruptsEnabled;
bool pendingInterrupt;
bool started;
@ -1547,7 +1547,7 @@ void GPUCommon::InterruptEnd(int listid) {
gstate.Restore(dl.context);
ReapplyGfxState();
}
dl.waitTicks = 0;
dl.waitUntilTicks = 0;
__GeTriggerWait(GPU_SYNC_LIST, listid);
// Make sure the list isn't still queued since it's now completed.

View file

@ -125,7 +125,7 @@ struct DisplayList {
DisplayListStackEntry stack[32];
int stackptr;
bool interrupted;
u64 waitTicks;
u64 waitUntilTicks;
bool interruptsEnabled;
bool pendingInterrupt;
bool started;
@ -371,7 +371,7 @@ public:
s64 GetListTicks(int listid) const {
if (listid >= 0 && listid < DisplayListMaxCount) {
return dls[listid].waitTicks;
return dls[listid].waitUntilTicks;
}
return -1;
}

View file

@ -51,7 +51,7 @@ void DrawSchedulerView(ImConfig &cfg) {
if (ImGui::BeginChild("event_list", ImVec2(300.0f, 0.0))) {
const CoreTiming::Event *event = CoreTiming::GetFirstEvent();
while (event) {
ImGui::Text("%s (%lld)", CoreTiming::GetEventTypes()[event->type].name, event->time - ticks);
ImGui::Text("%s (%lld): %d", CoreTiming::GetEventTypes()[event->type].name, event->time - ticks, (int)event->userdata);
event = event->next;
}
ImGui::EndChild();
@ -195,6 +195,9 @@ void WaitIDToString(WaitType waitType, SceUID waitID, char *buffer, size_t bufSi
case WAITTYPE_SLEEP:
case WAITTYPE_HLEDELAY:
case WAITTYPE_UMD:
case WAITTYPE_NONE:
case WAITTYPE_VBLANK:
case WAITTYPE_MICINPUT:
truncate_cpy(buffer, bufSize, "-");
return;
default:
@ -311,7 +314,7 @@ static void DrawFilesystemBrowser(ImConfig &cfg) {
std::string path;
char desc[256];
fs.system->Describe(desc, sizeof(desc));
char fsTitle[256];
char fsTitle[512];
snprintf(fsTitle, sizeof(fsTitle), "%s - %s", fs.prefix.c_str(), desc);
if (ImGui::TreeNode(fsTitle)) {
auto system = fs.system;
@ -852,10 +855,16 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
Core_Break("Menu:Break");
}
break;
default:
break;
}
ImGui::Separator();
ImGui::MenuItem("Ignore bad memory accesses", nullptr, &g_Config.bIgnoreBadMemAccess);
ImGui::MenuItem("Break on frame timeout", nullptr, &g_Config.bBreakOnFrameTimeout);
ImGui::MenuItem("Don't break on start", nullptr, &g_Config.bAutoRun); // should really invert this bool!
ImGui::MenuItem("Fast memory", nullptr, &g_Config.bFastMemory);
ImGui::Separator();
/*
// Symbol stuff. Move to separate menu?
// Doesn't quite seem to work yet.
@ -886,6 +895,7 @@ void ImDebugger::Frame(MIPSDebugInterface *mipsDebug, GPUDebugInterface *gpuDebu
if (ImGui::MenuItem("Take screenshot")) {
g_TakeScreenshot = true;
}
ImGui::MenuItem("Save screenshot as .png", nullptr, &g_Config.bScreenshotsAsPNG);
if (ImGui::MenuItem("Restart graphics")) {
System_PostUIMessage(UIMessage::RESTART_GRAPHICS);
}
@ -1157,6 +1167,11 @@ void ImDisasmWindow::Draw(MIPSDebugInterface *mipsDebug, ImConfig &cfg, CoreStat
disasmView_.setCurAddress(gotoAddr_);
disasmView_.scrollAddressIntoView();
}
ImGui::SameLine();
if (ImGui::Button("Go")) {
disasmView_.setCurAddress(gotoAddr_);
disasmView_.scrollAddressIntoView();
}
if (ImGui::BeginTable("main", 2)) {
ImGui::TableSetupColumn("left", ImGuiTableColumnFlags_WidthFixed);

View file

@ -242,9 +242,11 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, GPUDebugInterface *gpuDebug) {
return;
}
ImGui::BeginDisabled(coreState != CORE_STEPPING_GE);
if (ImGui::Button("Run/Resume")) {
Core_Resume();
}
ImGui::EndDisabled();
ImGui::SameLine();
ImGui::TextUnformatted("Break:");
ImGui::SameLine();
@ -302,6 +304,10 @@ void ImGeDebuggerWindow::Draw(ImConfig &cfg, GPUDebugInterface *gpuDebug) {
// Display any pending step event.
if (GPUDebug::GetBreakNext() != GPUDebug::BreakNext::NONE) {
ImGui::Text("Step pending (waiting for CPU): %s", GPUDebug::BreakNextToString(GPUDebug::GetBreakNext()));
ImGui::SameLine();
if (ImGui::Button("Cancel step")) {
GPUDebug::SetBreakNext(GPUDebug::BreakNext::NONE);
}
}
// Let's display the current CLUT.

View file

@ -75,7 +75,7 @@ bool MainThread_Ready() {
return g_inLoop;
}
static bool Core_Run(GraphicsContext *ctx) {
static bool Run(GraphicsContext *ctx) {
System_Notify(SystemNotification::DISASSEMBLY);
while (true) {
if (GetUIState() != UISTATE_INGAME) {
@ -127,11 +127,11 @@ static void EmuThreadFunc(GraphicsContext *graphicsContext) {
NativeInitGraphics(graphicsContext);
while (emuThreadState != (int)EmuThreadState::QUIT_REQUESTED) {
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
// We're here again, so the game quit. Restart Run() which controls the UI.
// This way they can load a new game.
if (!Core_IsActive())
UpdateUIState(UISTATE_MENU);
if (!Core_Run(g_graphicsContext)) {
if (!Run(g_graphicsContext)) {
emuThreadState = (int)EmuThreadState::QUIT_REQUESTED;
}
}
@ -338,11 +338,11 @@ void MainThreadFunc() {
}
} else {
while (GetUIState() != UISTATE_EXIT) { // && GetUIState() != UISTATE_EXCEPTION
// We're here again, so the game quit. Restart Core_Run() which controls the UI.
// We're here again, so the game quit. Restart Run() which controls the UI.
// This way they can load a new game.
if (!Core_IsActive())
UpdateUIState(UISTATE_MENU);
Core_Run(g_graphicsContext);
Run(g_graphicsContext);
if (coreState == CORE_BOOT_ERROR) {
break;
}
@ -351,7 +351,7 @@ void MainThreadFunc() {
Core_Stop();
if (!useEmuThread) {
// Process the shutdown. Without this, non-GL delays 800ms on shutdown.
Core_Run(g_graphicsContext);
Run(g_graphicsContext);
}
Core_WaitInactive();

View file

@ -1055,7 +1055,6 @@ namespace MainWindow
if (DragQueryFile(hdrop, 0, filename, ARRAY_SIZE(filename)) != 0) {
const std::string utf8_filename = ReplaceAll(ConvertWStringToUTF8(filename), "\\", "/");
System_PostUIMessage(UIMessage::REQUEST_GAME_BOOT, utf8_filename);
Core_Resume();
}
}
DragFinish(hdrop);