Skip to content

Conversation

@stephanmeesters
Copy link

@stephanmeesters stephanmeesters commented Jan 27, 2026

Merge by rebase

This PR adds Tracy profiler to the CMake presets win32-profile and win32-vcpkg-profile.

A variable RTS_BUILD_OPTION_PROFILE_TRACY is added to enable Tracy. Enabling this will disable the old profiler.

It is not added to the vc6-profile because Tracy library can't compile against it. The preset mingw-w64-i686-profile is also skipped as this preset does not build yet (see #2163).

Library include

Tracy is added as a package to VCPKG (version 0.11.1) and as a CMake FetchContent_Declare (version 0.13.1). These are the latest available versions at the time. Unfortunately the VCPKG is old, but the VCPKG Github has PR's going to update Tracy to the latest version. The version 0.13.1 improves coloring immensely, which is important for at a glance seeing if we are render-bound of update-bound.

Tracy themselves recommend adding the library as a CMake include because the version of the library that is included in the game must match exactly with the version of their main executable tracy-profiler.exe. This can be guaranteed by building and copying tracy-profiler.exe to the build dir, however we can not do this right now as it requires a 64 bit compile.

What are we tracing?

  • Frame markers (start-end of each frame)
  • Zones
  • Logic frame number
  • Pathfinding count of paths and cells
  • Messages ("started game with map Alpine Assault" ..)

A number of zones were picked that capture the majority of processing time, and will hopefully be useful for profiling sessions.

Performance impact

Tracy itself has a negligible impact, however the frame capturing does have a minor impact (0.5ms average per frame). I have done my best to optimize the frame capturing by downscaling the backbuffer on the GPU side before copying to the CPU. It will be possible to simplify some of this code by moving from DX8 to DX9 and perhaps increase performance too.

Future work

It should be determined whether this will be sufficient to replace the old profiling code. At that point, and when all other profiles build, we can activate Tracy using only RTS_BUILD_OPTION_PROFILE. Other interesting things to trace would be a plot of the memory usage.

Todo

  • Replicate to Generals

Example of a capture. Render bound frame (top), update bound frame (bottom)
tracy

@stephanmeesters stephanmeesters marked this pull request as ready for review January 27, 2026 22:29
@greptile-apps
Copy link

greptile-apps bot commented Jan 27, 2026

Greptile Overview

Greptile Summary

integrated Tracy profiler (v0.13.1 for FetchContent, v0.11.1 for VCPKG) into the win32-profile and win32-vcpkg-profile CMake presets, replacing the old profiler when RTS_BUILD_OPTION_PROFILE_TRACY is enabled

Major changes:

  • added Tracy as a VCPKG dependency and CMake FetchContent fallback
  • created conditional compilation macros in rts/profile.h that route to Tracy or provide no-op stubs
  • instrumented game loop with FrameMark and comprehensive ZoneScopedN/ZoneScopedNC zones across logic update, rendering pipeline, and AI subsystems
  • implemented GPU-accelerated frame capture with DirectX 8 downscaling and BGRA-to-RGBA pixel shader conversion
  • added TracyPlot metrics for logical frame number and pathfinding statistics (cells examined, paths found)
  • added TracyMessage markers for game start/end events

Minor style issues:

  • cmake/tracy.cmake missing required GPL-3.0 license header and Doxygen documentation (see custom rule c1850c23-ecc8-49a8-a6e9-ffb44120e6b3)
  • TRACY_FRAMEIMAGE_SIZE defined in header rather than CMake build config (minor deviation from custom rule 9aca79ba-17d4-4c71-918f-10816f7fc751)

The implementation is well-structured with proper conditional compilation, comprehensive profiling coverage, and an optimized frame capture approach that minimizes performance impact

Confidence Score: 4.5/5

  • safe to merge with minor style improvements recommended
  • comprehensive Tracy integration with proper conditional compilation, well-placed profiling zones, and optimized frame capture implementation; only minor style violations regarding file headers and constant placement
  • cmake/tracy.cmake needs license header added per project standards

Important Files Changed

Filename Overview
cmake/tracy.cmake added FetchContent configuration for Tracy v0.13.1, missing required header prologue
cmake/config-build.cmake added RTS_BUILD_OPTION_PROFILE_TRACY option and conditional Tracy setup logic
Core/Libraries/Include/rts/profile.h added Tracy header includes and macro stubs, TRACY_FRAMEIMAGE_SIZE defined in header instead of CMake
GeneralsMD/Code/GameEngineDevice/Source/W3DDevice/GameClient/W3DDisplay.cpp implemented Tracy frame capture with GPU downscaling and BGRA-to-RGBA pixel shader, added profiling zones
GeneralsMD/Code/GameEngine/Source/GameLogic/System/GameLogic.cpp added Tracy zones to major game logic subsystems and plot for logic frame number
GeneralsMD/Code/GameEngine/Source/GameLogic/AI/AIPathfind.cpp added Tracy zones to pathfinding and plots for pathfinding cells/paths, removed DEBUG_QPF guards

Sequence Diagram

sequenceDiagram
    participant GC as GameClient
    participant GL as GameLogic
    participant D as Display
    participant W3DD as W3DDisplay
    participant W3DV as W3DView
    participant W3DS as W3DScene
    participant DX8 as DX8Wrapper
    participant Tracy as Tracy Profiler

    Note over GC: Game Loop Start
    GC->>Tracy: FrameMark
    GC->>Tracy: ZoneScopedNC("Render")
    
    Note over GL: Logic Update
    GL->>Tracy: ZoneScopedNC("GameLogic::update")
    GL->>Tracy: TracyPlot("LogicFrame", frame)
    GL->>GL: Update ScriptEngine, TerrainLogic, AI, etc
    GL->>Tracy: Multiple ZoneScopedN for subsystems
    
    Note over GC: Render Phase
    GC->>D: DRAW()
    D->>W3DD: draw()
    W3DD->>Tracy: ZoneScopedN("Render::W3DDisplay::...")
    
    W3DD->>W3DV: draw()
    W3DV->>Tracy: ZoneScopedN("Render::DisplayDraw::W3DView")
    W3DV->>W3DS: Render()
    W3DS->>Tracy: ZoneScopedN("Render::W3DScene::...")
    W3DS->>W3DS: Render scene passes
    
    W3DD->>DX8: End_Render()
    DX8->>Tracy: ZoneScopedN("Render::VSync")
    DX8->>DX8: Present()
    
    W3DD->>W3DD: TracyCaptureImage()
    W3DD->>Tracy: ZoneScopedN("Render::W3DDisplay::TracyFrameImage")
    W3DD->>DX8: Copy backbuffer to intermediate texture
    W3DD->>DX8: Downscale with pixel shader (BGRA→RGBA)
    W3DD->>Tracy: FrameImage(pixels, width, height)
    
    Note over GC: Frame Complete
Loading

Copy link

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

@Caball009
Copy link

Would you mind adding a few images or a short video to the first post?

@stephanmeesters
Copy link
Author

stephanmeesters commented Jan 29, 2026

Would you mind adding a few images or a short video to the first post?

Done. Added examples.

I've noticed that it's important to use -win otherwise the frame image capture will use your screen resolution and not the native game resolution so it's much slower... I've tested using 1080p

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants