Skip to content

Massive performance degradation with DrawEntireTerrain=Yes #2743

Description

@xezon

Reported by 2 users. Probably comes from the recent heightmap changes. Needs fixing.

Activity

  1. self-assigned this
    on May 23, 2026
  2. added
    CriticalSeverity: Minor < Major < Critical < Blocker
    on May 23, 2026
  3. added theissue type on May 23, 2026
  4. added
    PerformanceIs a performance concern
    GenRelates to Generals
    ZHRelates to Zero Hour
    ThisProjectThe issue was introduced by this project, or this task is specific to this project
    ModRelates to Mods or modding
    on May 23, 2026
  5. sailro commented on Jun 12, 2026

    @sailro

    I looked into this together with the related water-at-zoom problem, and it turned out to be two distinct issues that people had been conflating through the DrawEntireTerrain=Yes workaround. I opened two complementary PRs.

    Background: why people often set DrawEntireTerrain=Yes (I was doing this)

    In the default path (DrawEntireTerrain=No) the terrain is only drawn within a window of tiles around the view center. At high camera zoom that window stops covering the visible ground, and on the many maps that keep a map-sized "Default Water" polygon, that water then renders behind the terrain window and the map looks flooded. The long-standing community workaround was to set DrawEntireTerrain=Yes so the whole map is always drawn — which hid the water bug but is what makes this issue (#2743) so slow.

    So there are really two problems:

    1. the rendering bug that drives people to the workaround, and
    2. the performance cost of the workaround itself.

    PR #2785 — fixes the rendering bug (default DrawEntireTerrain=No path)

    [#2785] sizes the normal draw window to the actual visible footprint instead of a fixed tile count: it projects the four view corners onto the ground (the same way updateCenter() already positions the window), grows the draw size just enough to span them, bounded by the map extent and snapped to whole vertex-buffer tiles. At normal zoom it is a no-op; the window only grows as you zoom out, on all maps.

    Effect on this issue: it removes the need for DrawEntireTerrain=Yes in the common case (no more water bleed-through at zoom without it). It deliberately does not touch the DrawEntireTerrain path, so on its own it does not fix #2743 — it just makes the slow workaround unnecessary for most users.

    PR #2786 — fixes this issue directly (DrawEntireTerrain=Yes path)

    [#2786] fixes the actual performance degradation. Root cause is two competing sources of truth for the terrain draw size:

    • WorldHeightMap::createDrawArea() force-overrides the stored draw size to the full map when DrawEntireTerrain=Yes (or the stretch size when StretchTerrain=Yes).
    • W3DView::updateTerrain() requests the normal draw size through HeightMapRenderObjClass::setTerrainDrawSize() every frame.

    setTerrainDrawSize() early-returns when the requested size equals the stored size, but the requested normal size can never match the stored full-map size. So every frame it re-ran initHeightData() + a full-map updateBlock(), and set m_needFullUpdate, making updateCenter() do a second full-map update — roughly two full terrain rebuilds (vertices + lighting) per frame. This regressed in #2677, which added the per-frame setTerrainDrawSize() call (W3DView.cpp, commit ccd8766) alongside the full-map override in createDrawArea() (commit c47b01a).

    The fix is two parts:

    1. Resolve the same StretchTerrain / DrawEntireTerrain overrides inside setTerrainDrawSize() (same precedence as createDrawArea()), so the unchanged-check matches and the terrain is no longer rebuilt every frame.
    2. That per-frame rebuild was, however, the only thing repainting the terrain when the vertex grid already covers the whole map — updateCenter() early-returns in that case (small maps, StretchTerrain, or DrawEntireTerrain) and never reached its m_needFullUpdate handling. So updateCenter() now honors a pending m_needFullUpdate in that early-return path with a single full updateBlock, ensuring lighting / device-reset / late-texture repaints still happen — but only when actually requested instead of every frame. (Without this second part, the first part alone left undrawn/untextured tiles on the shell map.)

    Steady-state cost returns to a one-time full update plus the normal full-map draw (i.e. the pre-#2677 cost), and terrain still updates correctly on lighting, device-reset and texture changes.

    TL;DR

    Tested in Zero Hour with DrawEntireTerrain=Yes: smooth in-game where the unpatched build was heavily laggy, and the shell map / in-game terrain renders correctly.

  6. sailro commented on Jun 21, 2026

    @sailro

    I really think #2786 is solving this performance issue (while #2785 extend support for larger resolutions). Happy to make changes or discuss anything.

    Thanks!

  7. xezon commented on Jun 21, 2026

    @xezon
    Author

    I will get to it when when I get the time. Luckily this is not an issue for retail players (because DrawEntireTerrain=No), but mod players.

  8. sailro commented on Jun 27, 2026

    @sailro

    I'm giving the root cause of the why I'm presenting those 2 PRs: I'm plying casually with my friends every weekend, we have all at least QHD monitors, and we were using only DrawEntireTerrain=Yes in our ini files for a very long time because we always had issues with water & limited terrain rendering. Note that we are using the GeneralsOnline fork.

    For like a month or two now, given the performance degradation, the GeneralsOnline fork even removed the reading of this DrawEntireTerrain parameter so we are stuck with this kind of unplayable rendering:

    Image
    • I tried to present a PR to the fork but they prefer this to be fixed upstream here (which is understandable)
    • I cannot craft custom builds for my friends and me because playing online -we had too much issues in lan- requires EasyAntiCheat to be active so no way we can use private builds even for our own private game.
    • So I would love to be able to play under good conditions :)
    • Again ready to rework everything if needed, from my POV the PR for fixing DrawEntireTerrain is quite self-contained to start : fix(heightmap): Prevent per-frame full terrain rebuild with DrawEntireTerrain #2786

    Thank you !

  9. stephanmeesters commented on Jun 27, 2026

    @stephanmeesters

    I cannot craft custom builds for my friends and me because playing online -we had too much issues in lan- requires EasyAntiCheat to be active so no way we can use private builds even for our own private game.

    As far as I know it should be possible to run a custom build of GO for matches between friends, but you need to pick "Generals Online Anti Cheat (GOAC)" not the EasyAntiCheat option

  10. sailro commented on Jun 27, 2026

    @sailro

    I cannot craft custom builds for my friends and me because playing online -we had too much issues in lan- requires EasyAntiCheat to be active so no way we can use private builds even for our own private game.

    As far as I know it should be possible to run a custom build of GO for matches between friends, but you need to pick "Generals Online Anti Cheat (GOAC)" not the EasyAntiCheat option

    Indeed I was able to build and connect online, the only subtlety I found was to set the USE_DEBUG_ON_LIVE_SERVER define to bypass the auto-update CRC gate. This one is specific to the GeneralsOnline fork.

    Thanks for the tip !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

CriticalSeverity: Minor < Major < Critical < BlockerGenRelates to GeneralsModRelates to Mods or moddingPerformanceIs a performance concernThisProjectThe issue was introduced by this project, or this task is specific to this projectZHRelates to Zero Hour

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions