Profiler (Modules) collects per-frame wall and thread CPU time, named inclusive sections, counters and GPU durations. It is off by default, so a disabled scope costs one branch. Application, WidgetApplication, VulkanContext and Canvas mark the frame phases (process, dispatch, advance, draw, paint, UI flush, acquire, submit, present). GpuTimer wraps Vulkan timestamp queries in a small ring that is read without stalling; the window frame and any RenderBuffer that asks for it report GPU time into the profiler. InputRecording stores raw window input with exact timing, pen pressure and tilt as a line-based text file, and InputRecorder captures it through a new raw tap in the InputCoalescer that sees every platform event before coalescing.
126 lines
No EOL
2.8 KiB
C++
126 lines
No EOL
2.8 KiB
C++
#include <cstdio>
|
|
|
|
#include "GraphicApplication.hpp"
|
|
#include "Profiler.hpp"
|
|
|
|
#include "imgui.h"
|
|
|
|
using namespace tp;
|
|
|
|
Application::Application() {
|
|
mWindow = Window::createWindow({ 1500, 900 });
|
|
mGraphics = new Graphics(mWindow);
|
|
mPerSecondTimer.setDuration(1000.f);
|
|
}
|
|
|
|
void Application::start() {
|
|
mEventHandler = new EventHandler();
|
|
mWindow->setEventHandler(mEventHandler);
|
|
|
|
mWindow->waitForReady();
|
|
|
|
mPreviousFrameTime = get_time();
|
|
mPerSecondTimer.reset();
|
|
runFrame();
|
|
}
|
|
|
|
void Application::step(halnf deltaMs) {
|
|
mWindow->processEvents(false);
|
|
runFrame(deltaMs);
|
|
}
|
|
|
|
void Application::finish() {
|
|
mWindow->setEventHandler(nullptr);
|
|
delete mEventHandler;
|
|
mEventHandler = nullptr;
|
|
}
|
|
|
|
void Application::run() {
|
|
start();
|
|
|
|
while (!mWindow->shouldClose()) {
|
|
mWindow->processEvents(!wantsFrame() || mWindow->isWaitingForFrame());
|
|
while (mWindow->isWaitingForFrame() && !mWindow->shouldClose())
|
|
mWindow->processEvents(true);
|
|
runFrame();
|
|
}
|
|
|
|
finish();
|
|
}
|
|
|
|
bool Application::wantsFrame() { return forceNewFrame() || mWindow->hasPendingWork(); }
|
|
|
|
void Application::runFrame() {
|
|
updateGlobalTime();
|
|
|
|
const time_ms now = get_time();
|
|
const halnf deltaMs = halnf(now - mPreviousFrameTime);
|
|
mPreviousFrameTime = now;
|
|
runFrame(deltaMs);
|
|
}
|
|
|
|
void Application::runFrame(halnf deltaMs) {
|
|
mFrameStart = get_time_ns();
|
|
Profiler::global().beginFrame();
|
|
|
|
{
|
|
TP_PROFILE_SCOPE("frame.process");
|
|
processPendingInput(deltaMs);
|
|
}
|
|
present();
|
|
updateFrameCounters();
|
|
|
|
Profiler::global().endFrame();
|
|
}
|
|
|
|
void Application::processPendingInput(halnf deltaMs) {
|
|
halnf deltaTime = deltaMs;
|
|
mWindow->flushPendingInput();
|
|
|
|
do {
|
|
TP_PROFILE_COUNT("input.events", 1);
|
|
mEventHandler->processEvent();
|
|
processFrame(mEventHandler, deltaTime);
|
|
deltaTime = 0;
|
|
mFramesProcessed++;
|
|
} while (mEventHandler->hasQueuedEvents());
|
|
}
|
|
|
|
void Application::present() {
|
|
TP_PROFILE_SCOPE("frame.present");
|
|
mGraphics->drawBegin();
|
|
{
|
|
TP_PROFILE_SCOPE("frame.draw");
|
|
drawFrame(mGraphics->getCanvas());
|
|
}
|
|
mGraphics->drawEnd();
|
|
mWindow->draw();
|
|
mFramesDrawn++;
|
|
}
|
|
|
|
void Application::updateFrameCounters() {
|
|
if (!mPerSecondTimer.isTimeout()) return;
|
|
mPerSecondTimer.reset();
|
|
|
|
mFramesProcessedPerSecond = mFramesProcessed;
|
|
mFramesDrawnPerSecond = mFramesDrawn;
|
|
mFramesDrawn = 0;
|
|
mFramesProcessed = 0;
|
|
}
|
|
|
|
void Application::processFrame(EventHandler* eventHandler, halnf deltaTime) {}
|
|
|
|
void Application::drawFrame(Canvas* canvas) {
|
|
// ImGui::Text("Frames processed per second: %f", mFramesProcessedPerSecond);
|
|
// ImGui::Text("Frames drawn per second: %f", mFramesDrawnPerSecond);
|
|
}
|
|
|
|
void Application::drawDebug() {
|
|
ImGui::Text("Frames processed per second: %f", this->mFramesProcessedPerSecond);
|
|
ImGui::Text("Frames drawn per second: %f", this->mFramesDrawnPerSecond);
|
|
}
|
|
|
|
Application::~Application() {
|
|
delete mGraphics;
|
|
Window::destroyWindow(mWindow);
|
|
} |