Apply clang-format across the whole tree
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.
This commit is contained in:
@@ -20,17 +20,13 @@
|
||||
|
||||
using namespace coop;
|
||||
|
||||
namespace
|
||||
{
|
||||
namespace {
|
||||
int g_failures = 0;
|
||||
void check(bool ok, const char* what)
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
if (ok) {
|
||||
std::printf(" ok: %s\n", what);
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
std::printf("FAIL: %s\n", what);
|
||||
++g_failures;
|
||||
}
|
||||
@@ -38,34 +34,29 @@ void check(bool ok, const char* what)
|
||||
|
||||
// The original policy: re-prime on any partial fill (`to_write < avail`). Kept here only to
|
||||
// contrast against the shipping RenderPacer.
|
||||
struct LegacyPacer
|
||||
{
|
||||
struct LegacyPacer {
|
||||
std::uint32_t prime_frames = 0;
|
||||
bool primed = false;
|
||||
std::uint32_t pump(std::uint32_t avail, std::uint32_t have, std::uint32_t /*padding*/)
|
||||
{
|
||||
if (!primed && have >= prime_frames)
|
||||
{
|
||||
if (!primed && have >= prime_frames) {
|
||||
primed = true;
|
||||
}
|
||||
if (!primed)
|
||||
{
|
||||
if (!primed) {
|
||||
return 0;
|
||||
}
|
||||
const std::uint32_t to_write = std::min(avail, have);
|
||||
if (to_write < avail)
|
||||
{
|
||||
if (to_write < avail) {
|
||||
primed = false; // the bug: a partial fill forces a full re-prime
|
||||
}
|
||||
return to_write;
|
||||
}
|
||||
};
|
||||
|
||||
struct SimResult
|
||||
{
|
||||
int underruns = 0; // device couldn't supply a full period (audible silence)
|
||||
struct SimResult {
|
||||
int underruns = 0; // device couldn't supply a full period (audible silence)
|
||||
std::uint32_t min_headroom = 0; // smallest device-buffer level seen after warm-up (cushion left)
|
||||
int withheld = 0; // ticks the policy refused to feed though the ring had >=1 period
|
||||
int withheld = 0; // ticks the policy refused to feed though the ring had >=1 period
|
||||
};
|
||||
|
||||
// Run one policy over a producer schedule, modelling an event-driven WASAPI render client.
|
||||
@@ -83,19 +74,14 @@ SimResult simulate(Pacer pacer, const std::vector<std::uint32_t>& producer, std:
|
||||
SimResult res;
|
||||
res.min_headroom = render_frames;
|
||||
bool warming = true; // ignore the initial fill-up before playback starts
|
||||
for (std::size_t t = 0; t < producer.size(); ++t)
|
||||
{
|
||||
for (std::size_t t = 0; t < producer.size(); ++t) {
|
||||
ring += producer[t]; // the game pushed this tick's frames into the ring
|
||||
// The device plays a period; its event then fires asking for more. If the buffer
|
||||
// can't supply a full period, the renderer plays silence -- an audible under-run.
|
||||
if (!warming)
|
||||
{
|
||||
if (device >= period)
|
||||
{
|
||||
if (!warming) {
|
||||
if (device >= period) {
|
||||
device -= period;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
++res.underruns;
|
||||
device = 0;
|
||||
}
|
||||
@@ -109,15 +95,12 @@ SimResult simulate(Pacer pacer, const std::vector<std::uint32_t>& producer, std:
|
||||
w = static_cast<std::uint32_t>(std::min<std::uint64_t>(w, ring));
|
||||
device += w;
|
||||
ring -= w;
|
||||
if (w > 0)
|
||||
{
|
||||
if (w > 0) {
|
||||
warming = false; // playback has begun
|
||||
}
|
||||
if (!warming)
|
||||
{
|
||||
if (!warming) {
|
||||
res.min_headroom = std::min(res.min_headroom, device);
|
||||
if (w == 0 && have >= period && avail >= period)
|
||||
{
|
||||
if (w == 0 && have >= period && avail >= period) {
|
||||
++res.withheld; // had at least a period to give and room to put it -- but didn't
|
||||
}
|
||||
}
|
||||
@@ -137,8 +120,7 @@ std::vector<std::uint32_t> jittery_schedule(std::uint32_t period, int ticks)
|
||||
p.reserve(ticks);
|
||||
std::uint64_t owed = 0;
|
||||
const std::uint32_t catch_up = period * 7 / 5; // 1.4x: clears the 2/7 stall backlog, but no faster
|
||||
for (int t = 0; t < ticks; ++t)
|
||||
{
|
||||
for (int t = 0; t < ticks; ++t) {
|
||||
owed += period;
|
||||
const std::uint32_t cap = (t % 7 < 2) ? 0u : catch_up; // stall 2/7 ticks, else catch up gently
|
||||
const std::uint32_t deliver = static_cast<std::uint32_t>(std::min<std::uint64_t>(owed, cap));
|
||||
@@ -178,10 +160,10 @@ int main()
|
||||
lp.prime_frames = kPrime;
|
||||
const SimResult n = simulate(np, sched, kRender, kPeriod);
|
||||
const SimResult l = simulate(lp, sched, kRender, kPeriod);
|
||||
std::printf(" (jittery: NEW under-runs=%d min_headroom=%u withheld=%d)\n", n.underruns,
|
||||
n.min_headroom, n.withheld);
|
||||
std::printf(" (jittery: OLD under-runs=%d min_headroom=%u withheld=%d)\n", l.underruns,
|
||||
l.min_headroom, l.withheld);
|
||||
std::printf(" (jittery: NEW under-runs=%d min_headroom=%u withheld=%d)\n", n.underruns, n.min_headroom,
|
||||
n.withheld);
|
||||
std::printf(" (jittery: OLD under-runs=%d min_headroom=%u withheld=%d)\n", l.underruns, l.min_headroom,
|
||||
l.withheld);
|
||||
// The defining pathology, measured directly (not timing-marginal): the old policy refuses
|
||||
// to feed data it has, repeatedly; the new policy never withholds once playing.
|
||||
check(n.withheld == 0, "jittery: new policy never withholds available data");
|
||||
@@ -212,8 +194,7 @@ int main()
|
||||
check(!p.primed, "true starvation (padding==0 && have==0) re-primes");
|
||||
}
|
||||
|
||||
if (g_failures == 0)
|
||||
{
|
||||
if (g_failures == 0) {
|
||||
std::printf("PASS render_pacer_test\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user