examples: Added --fixed-fps and --screenshot for deterministic captures. (#3998)

This commit is contained in:
Branimir Karadžić
2026-09-25 15:29:53 -07:00
committed by GitHub
parent c00cc181cc
commit d79de7ac63
6 changed files with 103 additions and 9 deletions
+6 -2
View File
@@ -523,6 +523,8 @@ public:
}
imguiCreate();
m_frameTime.reset();
}
int32_t shutdown() override
@@ -596,8 +598,7 @@ public:
{
if (bgfx::isValid(m_checkerboard) )
{
static int64_t timeOffset = bx::getHPCounter();
const float time = float( (bx::getHPCounter()-timeOffset)/double(bx::getHPFrequency() ) );
const float time = bx::toSeconds<float>(m_frameTime.getDurationTime() );
const float animate = float(m_animate)*0.5f;
const float xx = bx::sin(time * 0.37f) * animate;
const float yy = bx::cos(time * 0.43f) * animate;
@@ -631,6 +632,8 @@ public:
{
if (!entry::processEvents(m_width, m_height, m_debug, m_reset, &m_mouseState) )
{
m_frameTime.frame();
imguiBeginFrame(m_mouseState.m_mx
, m_mouseState.m_my
, (m_mouseState.m_buttons[entry::MouseButton::Left ] ? IMGUI_MBUT_LEFT : 0)
@@ -832,6 +835,7 @@ public:
}
entry::MouseState m_mouseState;
FrameTime m_frameTime;
uint32_t m_width;
uint32_t m_height;
+9 -3
View File
@@ -25,15 +25,21 @@ struct FrameTime
///
void reset()
{
m_start = m_current;
frame();
m_current = bx::getNow();
m_start = m_current;
m_last = m_current;
}
///
void frame()
{
const bx::Ticks step = entry::getFixedTimeStep();
m_last = m_current;
m_current = bx::getNow();
m_current = bx::Ticks(bx::InitZero) == step
? bx::getNow()
: m_current + step
;
}
///
+70 -1
View File
@@ -7,6 +7,7 @@
#include <bx/commandline.h>
#include <bx/file.h>
#include <bx/sort.h>
#include <bx/timer.h>
#include <bgfx/bgfx.h>
#include <time.h>
@@ -553,6 +554,71 @@ BX_PRAGMA_DIAGNOSTIC_POP();
return s_numApps;
}
static bx::Ticks s_fixedTimeStep = bx::InitZero;
bx::Ticks getFixedTimeStep()
{
return s_fixedTimeStep;
}
///
struct TestRun
{
TestRun(int _argc, const char* const* _argv)
: m_frame(0)
, m_screenshotFrame(0)
{
bx::CommandLine cmdLine(_argc, _argv);
const char* screenshot = cmdLine.findOption("screenshot");
if (NULL != screenshot)
{
bx::strCopy(m_screenshot, sizeof(m_screenshot), screenshot);
m_screenshotFrame = 60;
const char* frame = cmdLine.findOption("screenshot-frame");
if (NULL != frame)
{
bx::fromString(&m_screenshotFrame, frame);
}
}
uint32_t fps = 0 != m_screenshotFrame ? 60 : 0;
const char* fixedFps = cmdLine.findOption("fixed-fps");
if (NULL != fixedFps)
{
bx::fromString(&fps, fixedFps);
}
s_fixedTimeStep = 0 != fps
? bx::Ticks(bx::Ticks::s_kFreq.ticks/fps)
: bx::Ticks(bx::InitZero)
;
}
///
bool frame()
{
if (0 == m_screenshotFrame)
{
return true;
}
++m_frame;
if (m_frame == m_screenshotFrame)
{
bgfx::requestScreenShot(BGFX_INVALID_HANDLE, m_screenshot);
}
return m_frame < m_screenshotFrame + 3;
}
uint32_t m_frame;
uint32_t m_screenshotFrame;
char m_screenshot[bx::kMaxFilePath];
};
int runApp(AppI* _app, int _argc, const char* const* _argv)
{
setWindowSize(kDefaultWindowHandle, s_width, s_height);
@@ -564,6 +630,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
bx::snprintf(title, BX_COUNTOF(title), "%S - %s", &exeName, _app->getName() );
setWindowTitle(kDefaultWindowHandle, title);
TestRun test(_argc, _argv);
_app->init(_argc, _argv, s_width, s_height);
bgfx::frame();
@@ -573,7 +641,8 @@ BX_PRAGMA_DIAGNOSTIC_POP();
#else
while (_app->update() )
{
if (0 != bx::strLen(s_restartApp) )
if (0 != bx::strLen(s_restartApp)
|| !test.frame() )
{
break;
}
+3
View File
@@ -373,6 +373,9 @@ namespace entry
///
void setRestartArgs(const char* _args);
///
bx::Ticks getFixedTimeStep();
} // namespace entry
#endif // ENTRY_H_HEADER_GUARD
+7 -3
View File
@@ -417,7 +417,11 @@ void showExampleDialog(entry::AppI* _app, const char* _errorText)
const bgfx::Stats* stats = bgfx::getStats();
const double toMsCpu = 1000.0/stats->cpuTimerFreq;
const double toMsGpu = 1000.0/stats->gpuTimerFreq;
const double frameMs = double(stats->cpuTimeFrame)*toMsCpu;
const bool fixedTime = bx::Ticks(bx::InitZero) != entry::getFixedTimeStep();
const double frameMs = fixedTime
? bx::toMilliseconds<double>(entry::getFixedTimeStep() )
: double(stats->cpuTimeFrame)*toMsCpu
;
s_frameTime.pushSample(float(frameMs) );
@@ -444,8 +448,8 @@ void showExampleDialog(entry::AppI* _app, const char* _errorText)
ImGui::PopStyleColor();
ImGui::Text("Submit CPU %0.3f, GPU %0.3f (L: %d)"
, double(stats->cpuTimeEnd - stats->cpuTimeBegin)*toMsCpu
, double(stats->gpuTimeEnd - stats->gpuTimeBegin)*toMsGpu
, fixedTime ? 0.0 : double(stats->cpuTimeEnd - stats->cpuTimeBegin)*toMsCpu
, fixedTime ? 0.0 : double(stats->gpuTimeEnd - stats->gpuTimeBegin)*toMsGpu
, stats->maxGpuLatency
);
+8
View File
@@ -531,6 +531,14 @@ struct OcornutImguiContext
const double freq = double(bx::getHPFrequency() );
io.DeltaTime = float(frameTime/freq);
#if USE_ENTRY
const bx::Ticks step = entry::getFixedTimeStep();
if (bx::Ticks(bx::InitZero) != step)
{
io.DeltaTime = bx::toSeconds<float>(step);
}
#endif // USE_ENTRY
io.AddMousePosEvent( (float)_mx, (float)_my);
io.AddMouseButtonEvent(ImGuiMouseButton_Left, 0 != (_button & IMGUI_MBUT_LEFT ) );
io.AddMouseButtonEvent(ImGuiMouseButton_Right, 0 != (_button & IMGUI_MBUT_RIGHT ) );