Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Core/GameEngine/Source/Common/FrameRateLimit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,22 @@ Real FrameRateLimit::wait(UnsignedInt maxFps)
}


// GeneralsX @doc These are the selectable RENDER frame-rate cap presets (the "FPS Limit"
// option in the UI). This cap is NOT the simulation speed: game logic always advances at a
// fixed LOGICFRAMES_PER_SECOND (30 Hz) regardless of the value chosen here. See FrameRateLimit::wait().
//
// IMPORTANT for input responsiveness: the main loop services input (SDL poll ->
// GameClient::UPDATE message processing) exactly ONCE PER RENDER FRAME, and FramePacer::update()
// then sleeps to hold this cap. Consequently the render FPS cap also sets how often the mouse is
// sampled: a low cap (e.g. 30) makes mouse selection/dragging feel laggy and can make fast-moving
// units hard to click, because input is only polled ~cap times/second -- while the simulation
// still runs at 30 Hz either way. A higher cap (60/120/...) does not speed up the game; it only
// makes input more responsive. (Root cause of a long "mouse input is delayed" investigation.)
const UnsignedInt RenderFpsPreset::s_fpsValues[] = {
30, 50, 56, 60, 65, 70, 72, 75, 80, 85, 90, 100, 110, 120, 144, 240, 480, UncappedFpsValue };

// The lowest selectable cap (30) must not drop below the logic rate, or input/render would starve
// the fixed-rate simulation.
static_assert(LOGICFRAMES_PER_SECOND <= 30, "Min FPS values need to be revisited!");

UnsignedInt RenderFpsPreset::getNextFpsValue(UnsignedInt value)
Expand Down
6 changes: 6 additions & 0 deletions GeneralsMD/Code/GameEngine/Source/Common/GameEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1101,6 +1101,12 @@ void GameEngine::execute()
}
}

// TheFramePacer->update() sleeps here to hold the render FPS cap (RenderFpsPreset /
// GlobalData::m_framesPerSecondLimit). Because input is serviced once per iteration of
// this loop (SDL poll + GameClient::UPDATE message processing, above), this pacing wait
// also throttles the input sampling rate. A low FPS cap therefore makes the mouse feel
// laggy (hard to click moving units) even though the fixed 30 Hz simulation is unchanged.
// See RenderFpsPreset::s_fpsValues in FrameRateLimit.cpp for the full explanation.
TheFramePacer->update();

// NOTE: TheDisplay->draw() is called via TheGameClient->UPDATE() above.
Expand Down
Loading