void DebugStats() { gpu->UpdateStats(); char stats[2048]; sprintf(stats, "Frames: %i\n" "DL processing time: %0.2f ms\n" "Kernel processing time: %0.2f ms\n" "Slowest syscall: %s : %0.2f ms\n" "Most active syscall: %s : %0.2f ms\n" "Draw calls: %i, flushes %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "Vertices Submitted: %i\n" "Cached Vertices Drawn: %i\n" "Uncached Vertices Drawn: %i\n" "FBOs active: %i\n" "Textures active: %i, decoded: %i\n" "Texture invalidations: %i\n" "Vertex shaders loaded: %i\n" "Fragment shaders loaded: %i\n" "Combined shaders loaded: %i\n", gpuStats.numFrames, gpuStats.msProcessingDisplayLists * 1000.0f, kernelStats.msInSyscalls * 1000.0f, kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)", kernelStats.slowestSyscallTime * 1000.0f, kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)", kernelStats.summedSlowestSyscallTime * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, gpuStats.numFBOs, gpuStats.numTextures, gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, gpuStats.numVertexShaders, gpuStats.numFragmentShaders, gpuStats.numShaders ); float zoom = 0.3f; /// g_Config.iWindowZoom; float soff = 0.3f; PPGeBegin(); PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000); PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000); PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF); PPGeEnd(); gpuStats.resetFrame(); kernelStats.ResetFrame(); }
void CalculateFPS() { static double highestFps = 0.0; static int lastFpsFrame = 0; static double lastFpsTime = 0.0; static double fps = 0.0; time_update(); double now = time_now_d(); if (now >= lastFpsTime + 1.0) { fps = (gpuStats.numFrames - lastFpsFrame) / (now - lastFpsTime); if (fps > highestFps) highestFps = fps; lastFpsFrame = gpuStats.numFrames; lastFpsTime = now; } char stats[50]; sprintf(stats, "VPS: %0.1f", fps); #ifdef USING_GLES2 float zoom = 0.7f; /// g_Config.iWindowZoom; float soff = 0.7f; #else float zoom = 0.5f; /// g_Config.iWindowZoom; float soff = 0.5f; #endif PPGeBegin(); PPGeDrawText(stats, 476 + soff, 4 + soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476 + -soff, 4 -soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476, 4, PPGE_ALIGN_RIGHT, zoom, 0xFF30FF30); PPGeEnd(); }
void PSPDialog::EndDraw() { PPGeEnd(); }
void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(HLE, "Enter VBlank %i", vbCount); isVblank = 1; // Fire the vblank listeners before we wake threads. __DisplayFireVblank(); // Wake up threads waiting for VBlank for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { if (--vblankWaitingThreads[i].vcountUnblock == 0) { __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0); vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--); } } // Trigger VBlank interrupt handlers. __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL); CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount + 1); // TODO: Should this be done here or in hleLeaveVblank? if (framebufIsLatched) { DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } gpuStats.numFrames++; // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { DebugStats(); } if (g_Config.bShowFPSCounter) { char stats[50]; sprintf(stats, "%0.1f", calculateFPS()); #ifdef USING_GLES2 float zoom = 0.7f; /// g_Config.iWindowZoom; float soff = 0.7f; #else float zoom = 0.5f; /// g_Config.iWindowZoom; float soff = 0.5f; #endif PPGeBegin(); PPGeDrawText(stats, 476 + soff, 4 + soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476 + -soff, 4 -soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476, 4, PPGE_ALIGN_RIGHT, zoom, 0xFF30FF30); PPGeEnd(); } // Draw screen overlays before blitting. Saves and restores the Ge context. // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. gstate_c.skipDrawReason &= ~SKIPDRAW_SKIPFRAME; bool throttle, skipFrame, skipFlip; DoFrameTiming(throttle, skipFrame, skipFlip); // Setting CORE_NEXTFRAME causes a swap. if (skipFrame) { gstate_c.skipDrawReason |= SKIPDRAW_SKIPFRAME; numSkippedFrames++; } else { numSkippedFrames = 0; } if (!skipFlip) { // Might've just quit / been paused. if (coreState == CORE_RUNNING) { coreState = CORE_NEXTFRAME; } CoreTiming::ScheduleEvent(0 - cyclesLate, afterFlipEvent, 0); gpu->CopyDisplayToOutput(); } // Returning here with coreState == CORE_NEXTFRAME causes a buffer flip to happen (next frame). // Right after, we regain control for a little bit in hleAfterFlip. I think that's a great // place to do housekeeping. }
void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(HLE, "Enter VBlank %i", vbCount); isVblank = 1; // Fire the vblank listeners before we wake threads. __DisplayFireVblank(); // Wake up threads waiting for VBlank for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { if (--vblankWaitingThreads[i].vcountUnblock == 0) { __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0); vblankWaitingThreads.erase(vblankWaitingThreads.begin() + i--); } } // Trigger VBlank interrupt handlers. __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED | PSP_INTR_ALWAYS_RESCHED, PSP_VBLANK_INTR, PSP_INTR_SUB_ALL); CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); // TODO: Should this be done here or in hleLeaveVblank? if (framebufIsLatched) { DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } // Draw screen overlays before blitting. Saves and restores the Ge context. gpuStats.numFrames++; // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { gpu->UpdateStats(); char stats[2048]; sprintf(stats, "Frames: %i\n" "DL processing time: %0.2f ms\n" "Kernel processing time: %0.2f ms\n" "Slowest syscall: %s : %0.2f ms\n" "Most active syscall: %s : %0.2f ms\n" "Draw calls: %i, flushes %i\n" "Cached Draw calls: %i\n" "Num Tracked Vertex Arrays: %i\n" "Vertices Submitted: %i\n" "Cached Vertices Drawn: %i\n" "Uncached Vertices Drawn: %i\n" "FBOs active: %i\n" "Textures active: %i, decoded: %i\n" "Texture invalidations: %i\n" "Vertex shaders loaded: %i\n" "Fragment shaders loaded: %i\n" "Combined shaders loaded: %i\n", gpuStats.numFrames, gpuStats.msProcessingDisplayLists * 1000.0f, kernelStats.msInSyscalls * 1000.0f, kernelStats.slowestSyscallName ? kernelStats.slowestSyscallName : "(none)", kernelStats.slowestSyscallTime * 1000.0f, kernelStats.summedSlowestSyscallName ? kernelStats.summedSlowestSyscallName : "(none)", kernelStats.summedSlowestSyscallTime * 1000.0f, gpuStats.numDrawCalls, gpuStats.numFlushes, gpuStats.numCachedDrawCalls, gpuStats.numTrackedVertexArrays, gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, gpuStats.numFBOs, gpuStats.numTextures, gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, gpuStats.numVertexShaders, gpuStats.numFragmentShaders, gpuStats.numShaders ); float zoom = 0.3f; /// g_Config.iWindowZoom; float soff = 0.3f; PPGeBegin(); PPGeDrawText(stats, soff, soff, 0, zoom, 0xCC000000); PPGeDrawText(stats, -soff, -soff, 0, zoom, 0xCC000000); PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFFFFFFF); PPGeEnd(); gpuStats.resetFrame(); kernelStats.ResetFrame(); } if (g_Config.bShowFPSCounter) { char stats[50]; sprintf(stats, "%0.1f", calculateFPS()); #ifdef USING_GLES2 float zoom = 0.7f; /// g_Config.iWindowZoom; float soff = 0.7f; #else float zoom = 0.5f; /// g_Config.iWindowZoom; float soff = 0.5f; #endif PPGeBegin(); PPGeDrawText(stats, 476 + soff, 4 + soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476 + -soff, 4 -soff, PPGE_ALIGN_RIGHT, zoom, 0xCC000000); PPGeDrawText(stats, 476, 4, PPGE_ALIGN_RIGHT, zoom, 0xFF30FF30); PPGeEnd(); } // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. gpu->CopyDisplayToOutput(); host->EndFrame(); #ifdef _WIN32 // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. time_update(); if (lastFrameTime == 0.0) lastFrameTime = time_now_d(); if (!GetAsyncKeyState(VK_TAB) && !PSP_CoreParameter().headLess) { while (time_now_d() < lastFrameTime + 1.0 / 60.0) { Common::SleepCurrentThread(1); time_update(); } // Advance lastFrameTime by a constant amount each frame, // but don't let it get too far behind. lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); } // We are going to have to do something about audio timing for platforms that // are vsynced to something that's not exactly 60fps.. #endif host->BeginFrame(); gpu->BeginFrame(); // Tell the emu core that it's time to stop emulating // Win32 doesn't need this. #ifndef _WIN32 coreState = CORE_NEXTFRAME; #endif }
void hleEnterVblank(u64 userdata, int cyclesLate) { int vbCount = userdata; DEBUG_LOG(HLE, "Enter VBlank %i", vbCount); isVblank = 1; // Fire the vblank listeners before we wake threads. __DisplayFireVblank(); // Wake up threads waiting for VBlank for (size_t i = 0; i < vblankWaitingThreads.size(); i++) { __KernelResumeThreadFromWait(vblankWaitingThreads[i].threadID, 0); } vblankWaitingThreads.clear(); // Trigger VBlank interrupt handlers. __TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED, PSP_VBLANK_INTR); CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1); // TODO: Should this be done here or in hleLeaveVblank? if (framebufIsLatched) { DEBUG_LOG(HLE, "Setting latched framebuffer %08x (prev: %08x)", latchedFramebuf.topaddr, framebuf.topaddr); framebuf = latchedFramebuf; framebufIsLatched = false; gpu->SetDisplayFramebuffer(framebuf.topaddr, framebuf.pspFramebufLinesize, framebuf.pspFramebufFormat); } // Draw screen overlays before blitting. Saves and restores the Ge context. gpuStats.numFrames++; // Yeah, this has to be the right moment to end the frame. Give the graphics backend opportunity // to blit the framebuffer, in order to support half-framerate games that otherwise wouldn't have // anything to draw here. gpu->CopyDisplayToOutput(); // Now we can subvert the Ge engine in order to draw custom overlays like stat counters etc. // Here we will be drawing to the non buffered front surface. if (g_Config.bShowDebugStats && gpuStats.numDrawCalls) { gpu->UpdateStats(); char stats[512]; sprintf(stats, "Frames: %i\n" "Draw calls: %i\n" "Draw flushes: %i\n" "Vertices Transformed: %i\n" "Textures active: %i\n" "Textures decoded: %i\n" "Vertex shaders loaded: %i\n" "Fragment shaders loaded: %i\n" "Combined shaders loaded: %i\n", gpuStats.numFrames, gpuStats.numDrawCalls, gpuStats.numFlushes, gpuStats.numVertsTransformed, gpuStats.numTextures, gpuStats.numTexturesDecoded, gpuStats.numVertexShaders, gpuStats.numFragmentShaders, gpuStats.numShaders ); float zoom = 0.7f; /// g_Config.iWindowZoom; PPGeBegin(); PPGeDrawText(stats, 0, 0, 0, zoom, 0xFFc0c0c0); PPGeEnd(); gpuStats.resetFrame(); } host->EndFrame(); #ifdef _WIN32 static double lastFrameTime = 0.0; // Best place to throttle the frame rate on non vsynced platforms is probably here. Let's try it. time_update(); if (lastFrameTime == 0.0) lastFrameTime = time_now_d(); if (!GetAsyncKeyState(VK_TAB)) { while (time_now_d() < lastFrameTime + 1.0 / 60.0) { Common::SleepCurrentThread(1); time_update(); } // Advance lastFrameTime by a constant amount each frame, // but don't let it get too far behind. lastFrameTime = std::max(lastFrameTime + 1.0 / 60.0, time_now_d() - 1.5 / 60.0); } // We are going to have to do something about audio timing for platforms that // are vsynced to something that's not exactly 60fps.. #endif host->BeginFrame(); gpu->BeginFrame(); // Tell the emu core that it's time to stop emulating // Win32 doesn't need this. #ifndef _WIN32 coreState = CORE_NEXTFRAME; #endif }