Run clang-format (the repo's .clang-format: LLVM base, 120 cols, tabs, Allman functions) over every source file so the tree is formatter-clean. Whitespace only -- no behavior change; full x64 + x86 suites pass. Also set SortIncludes: false in .clang-format. Windows include order is load-bearing (windows.h must precede tlhelp32.h / mmreg.h / xinput.h / dinput.h; winsock2.h must precede windows.h), and the default alphabetical sort reorders tlhelp32.h ahead of windows.h -- a build break. Leaving order alone keeps the manual, correct grouping.
44 lines
1.7 KiB
C++
44 lines
1.7 KiB
C++
// Shared helper for the per-backend present-thread overhead guards.
|
|
//
|
|
// The capture path (Present / SwapBuffers hook, or the Vulkan read-back) runs on the game's present
|
|
// thread. If it stalls there, it caps the game's frame rate -- the Vulkan layer did exactly this,
|
|
// dropping a 144 FPS game to ~3 FPS by spending ~370 ms per present reading write-combined memory.
|
|
// Each GPU backend's in-process hook test measures the wall time its present spends with the hook
|
|
// live vs. removed and asserts the added cost stays under one display frame, so a future regression
|
|
// that puts a synchronous read-back / stall back on the present thread fails the test.
|
|
#pragma once
|
|
|
|
#include <windows.h>
|
|
|
|
namespace cooptest {
|
|
inline double now_ms()
|
|
{
|
|
LARGE_INTEGER f, c;
|
|
QueryPerformanceFrequency(&f);
|
|
QueryPerformanceCounter(&c);
|
|
return 1000.0 * static_cast<double>(c.QuadPart) / static_cast<double>(f.QuadPart);
|
|
}
|
|
|
|
// Average wall time of `present()` over n frames, calling `render()` (untimed) before each so a
|
|
// fresh frame is produced. Returns milliseconds per present.
|
|
template <class RenderFn, class PresentFn>
|
|
double avg_present_ms(int n, RenderFn render, PresentFn present)
|
|
{
|
|
render();
|
|
present(); // warm (first present/resource setup)
|
|
double total = 0;
|
|
for (int i = 0; i < n; ++i) {
|
|
render();
|
|
const double a = now_ms();
|
|
present();
|
|
total += now_ms() - a;
|
|
}
|
|
return n > 0 ? total / n : 0.0;
|
|
}
|
|
|
|
// One 60 Hz display frame. The capture's added present-thread cost must stay well under this or it
|
|
// throttles the game; the Vulkan bug added ~370 ms (22x over budget). Generous on purpose -- the
|
|
// guard targets the catastrophic-stall class, not micro-overhead, so it never flakes on jitter.
|
|
inline constexpr double kPresentOverheadBudgetMs = 16.7;
|
|
} // namespace cooptest
|