Skip to content

Add compile-time selectable profiling backend with Tracy integration#3239

Merged
halx99 merged 16 commits into
axmolengine:devfrom
unfiv:tracy_profiler
Jul 19, 2026
Merged

Add compile-time selectable profiling backend with Tracy integration#3239
halx99 merged 16 commits into
axmolengine:devfrom
unfiv:tracy_profiler

Conversation

@unfiv

@unfiv unfiv commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces compile-time selectable profiling backends for Axmol and provides an initial integration with the Tracy profiler.

The implementation preserves Tracy's zero-runtime-abstraction design by resolving the backend entirely at compile time. The existing built-in Axmol profiler remains unchanged and continues to work independently.

Currently supported backends:

  • NONE (no-op)
  • TRACY

The design allows additional profiling backends to be integrated without changing engine code.


Motivation

While Axmol includes its own built-in profiler, it currently lacks integration with modern external profiling tools.

The goals of this implementation were:

  • integrate Tracy following existing Axmol CMake conventions;
  • keep profiler selection under the control of the final application;
  • preserve Tracy's native compile-time instrumentation model;
  • avoid runtime wrappers or virtual interfaces;
  • provide a simple extension point for future profiling backends.

Design

The profiling backend is selected entirely at compile time.

                CMake

      AX_PROFILER_BACKEND
               │
               ▼
   target_compile_definitions(...)
               │
               ▼
          Profiling.h
               │
      +--------+--------+
      |                 |
      ▼                 ▼
 ProfilingBackend    ProfilingBackend
      Tracy              No-op

Engine code depends only on the profiling facade.

When NONE is selected, profiling macros expand to no-op and generate no runtime code.

The existing built-in Axmol profiler is unaffected by this change.


CMake

New cache option:

set(AX_PROFILER_BACKEND "NONE" CACHE STRING "Profiling backend")

Supported values:

  • NONE
  • TRACY

Example (included in the default template AXGameEngineOptions.cmake):

set(AX_PROFILER_BACKEND "TRACY" CACHE STRING "Profiling backend" FORCE)

Public API

Introduces backend-independent profiling macros:

AX_PROFILER_ZONE_SCOPED;
AX_PROFILER_ZONE_SCOPED_N("Loading");
AX_PROFILER_FRAME_MARK;
AX_PROFILER_THREAD_NAME("Worker");

The engine itself never references Tracy directly outside the backend implementation.


Tracy integration

This PR includes:

  • Tracy client integration
  • build system support
  • compile-time backend selection
  • initial CPU instrumentation covering the main engine frame loop and its primary subsystems
  • frame marker
  • worker thread naming support

Validation

Tested with:

  • existing Axmol project;
  • a newly generated project from the official template;
  • Debug configuration: live capture using Tracy Viewer, frame markers, CPU zones, worker thread profiling;
  • Release configuration (AX_PROFILER_BACKEND=NONE, default): confirmed via CMake cache, build log, and binary inspection of axmol.lib that no Tracy symbols or strings are present, confirming zero overhead when profiling is disabled.

Release with AX_PROFILER_BACKEND=TRACY has not yet been validated end-to-end and is left for a follow-up.


Screenshot

Initial Axmol engine instrumentation in Tracy Viewer. The screenshot shows frame markers, CPU zones, subsystem timing, statistics and worker thread profiling.

final_tracy_axmol

Notes

This PR intentionally does not replace or modify the existing built-in Axmol profiler.

The built-in profiler and the new compile-time backend infrastructure coexist independently.

The current instrumentation intentionally focuses on the primary CPU frame flow and the major engine subsystems. More fine-grained zones can be added incrementally without changing the profiling infrastructure.

Prebuilt workflow fix

An issue was found where projects built via the "compile engine once, link
prebuilt" workflow (-DAX_PREBUILT_DIR=...) failed with:

error C1189: #error: "No valid profiling backend selected"

Root cause: in prebuilt mode, the consumer project links against an
already-built axmol library rather than compiling it from source, so the
engine's own CMakeLists.txt (including the block that applies
AX_PROFILER_BACKEND_* as a compile definition) never runs for the consumer
project. The consumer's own translation units still include Profiling.h,
but never receive the backend macro.

Fix: extracted the backend-selection logic into a shared macro,
ax_apply_profiler_backend(target scope), in AXBuildHelpers.cmake
following the existing precedent of ax_config_pred, which is applied both
in the engine's own CMakeLists.txt and in AXLinkHelpers.cmake's
ax_link_cxx_prebuilt for the same reason (compile definitions don't
propagate to prebuilt consumers). This avoids duplicating the same
if/elseif logic in two places.

Note: ax_config_pred itself was not reused directly, since it is designed
for boolean on/off options (if(${pred})), while AX_PROFILER_BACKEND is a
string enum (NONE/TRACY) — passing it through ax_config_pred would
always evaluate truthy regardless of value, which is not the desired
behavior.

This also adds an explicit message(FATAL_ERROR ...) for unrecognized
AX_PROFILER_BACKEND values, which was previously silently ignored.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@unfiv
unfiv marked this pull request as draft July 18, 2026 12:08
@unfiv
unfiv marked this pull request as ready for review July 18, 2026 18:31
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@halx99

halx99 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

Thanks for your contribution and the PR!

For optional features that are disabled by default, we recommend downloading their third-party library dependencies dynamically during the CMake configuration stage, rather than bundling them directly or downloading them unconditionally.

Please refer to the following implementation and a previous PR for reference:

Could you please update the PR to follow this approach? Thank you!

@unfiv

unfiv commented Jul 19, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for your contribution and the PR!

For optional features that are disabled by default, we recommend downloading their third-party library dependencies dynamically during the CMake configuration stage, rather than bundling them directly or downloading them unconditionally.

Please refer to the following implementation and a previous PR for reference:

Could you please update the PR to follow this approach? Thank you!

Sure, it totally makes sense, will rework. Thank you!

@halx99 halx99 added this to the 3.0.0 milestone Jul 19, 2026
@halx99 halx99 added the enhancement New feature or request label Jul 19, 2026
@halx99

halx99 commented Jul 19, 2026

Copy link
Copy Markdown
Collaborator

lgtm

@halx99
halx99 merged commit 765fb7f into axmolengine:dev Jul 19, 2026
20 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants