Skip to content

Comments

Test comparison tooling and extended tracing instrumentation#2774

Open
ppenenko wants to merge 17 commits intoAcademySoftwareFoundation:mainfrom
autodesk-forks:ppenenko/diff_test_runs
Open

Test comparison tooling and extended tracing instrumentation#2774
ppenenko wants to merge 17 commits intoAcademySoftwareFoundation:mainfrom
autodesk-forks:ppenenko/diff_test_runs

Conversation

@ppenenko
Copy link
Contributor

@ppenenko ppenenko commented Feb 13, 2026

Summary

This PR adds test suite options, extended Perfetto tracing instrumentation, and Python-based test comparison tooling to MaterialX, building on the tracing infrastructure from PR #2742.

1. Test suite options

New options in _options.mtlx that control how the render test suite collects performance data:

  • envSampleCount: Configurable IBL sample count (default unchanged). Lower values (1–16) make shader complexity a larger fraction of GPU time, enabling game-representative performance comparisons.
  • framesPerMaterial: Number of render iterations per material for GPU timing stability. Higher values (100s) yield statistically meaningful averages when combined with warm-up frame analysis.

2. Extended tracing instrumentation (C++)

Building on the Perfetto tracing from #2742, this PR adds instrumentation to additional codegen and rendering hot paths. This also required conditionally linking MaterialXTrace to MaterialXGenShader, which was not needed by #2742 (tracing was only in test code) but is now required for the new codegen instrumentation.

  • Shader codegen: ShaderGraph traversal (createConnectedNodes, addUpstreamDependencies, createNode), ShaderGenerator emit functions (emitFunctionDefinitions, emitFunctionCalls, getImplementation), and CompoundNode operations

    image
  • GLSL build: GlslProgram::build() and DumpGeneratedCode

  • GPU timing: New MX_TRACE_ASYNC macro and AsyncTrack infrastructure for emitting GPU timer query results on a dedicated Perfetto track, enabling render-time-per-material analysis

  • Multi-frame rendering: Uses the framesPerMaterial option (see above) for repeated renders with GL timer queries

3. Python comparison scripts (MaterialXTest.diff_test_runs)

A new Python package under python/MaterialXTest/diff_test_runs/ provides three scripts for comparing pairs of MaterialX test suite output directories (baseline vs. optimized). The trace comparison script (diff_traces.py) consumes the Perfetto traces and GPU track events produced by the instrumentation above.

Script Purpose
diff_images.py Perceptual image comparison using NVIDIA FLIP, with HTML side-by-side reports. Below is an example diff between two test runs with 1024 and 1 environment samples, respectively:
image
diff_traces.py Perfetto trace comparison with per-material CPU slice and GPU render-time analysis, multiple --slice filters, --warmup-frames burn-in period, inline SVG charts in HTML reports, e.g. image
diff_shaders.py Offline shader analysis: line count, SPIR-V binary size, glslangValidator compile time, spirv-opt optimization time; auto-discovers Vulkan SDK tools in PATH, e.g. image
_report.py Shared utilities for comparison tables, SVG chart generation, and HTML report building

Key features of the scripts:

  • HTML reports with interactive, searchable inline SVG bar charts
  • Sorted comparison tables showing per-material deltas (absolute and percentage)
  • Summary statistics (mean, median, best/worst) for quick assessment
  • Configurable filtering (--min-delta-ms, --min-delta-pct) to focus on significant changes
  • Warm-up frame support (--warmup-frames) to discard initial GPU frames for more stable averages

Motivation

This tooling was developed to measure and validate shader generation optimizations (early lobe pruning, dead code elimination) in a companion branch. The infrastructure is generally useful for:

  • Regression testing: Detect visual regressions from codegen changes via FLIP
  • Performance profiling: Compare shader generation time, compilation time, and GPU render time across branches
  • Shader quality analysis: Quantify code size and SPIR-V improvements from optimizations

Test plan

  • Verified all three comparison scripts produce correct HTML reports when comparing two test suite runs from the same build (expected: noise-level differences)
  • Verified diff_traces.py correctly processes Perfetto traces with CPU slices (GenerateShader, CompileShader, etc.) and GPU async track events
  • Verified diff_images.py produces FLIP-based perceptual difference reports
  • Verified diff_shaders.py compiles dumped GLSL to SPIR-V and reports LOC/size/timing deltas
  • Verified C++ build with MATERIALX_BUILD_PERFETTO_TRACING=ON on Windows (MSVC)
  • Verified C++ build with MATERIALX_BUILD_PERFETTO_TRACING=OFF (no-op macros, no link dependencies)

Related


Assisted-by: Claude (Anthropic) via Cursor IDE
Signed-off-by: Pavlo Penenko <pavlo.penenko@autodesk.com>

Add configurable environment radiance sample count to test suite options,
allowing game-representative performance testing (1-16 samples) vs reference
quality (1024+ samples). Lower sample counts make shader complexity a larger
fraction of GPU time, enabling meaningful runtime performance comparisons.
Python package (MaterialXTest.diff_test_runs) with three comparison
scripts and shared reporting utilities:

  diff_images.py  -- perceptual image comparison via NVIDIA FLIP,
                     with HTML side-by-side reports
  diff_traces.py  -- Perfetto trace comparison with per-material
                     CPU slice and GPU render time analysis,
                     multiple --slice filters, --warmup-frames
                     burn-in, inline SVG charts
  diff_shaders.py -- offline shader analysis (LOC, SPIR-V size,
                     compile time, spirv-opt time); auto-discovers
                     Vulkan SDK tools in PATH
  _report.py      -- shared comparison tables, SVG chart generation,
                     and HTML report builder
Declare the new test suite options so the C++ test runner can read
them from the options file.  Also reset enableTracing default to
false (opt-in for profiling runs).
Added MX_TRACE markers to key codegen functions for profiling:
- ShaderGraph: createConnectedNodes, addUpstreamDependencies, createNode
- ShaderGenerator: getImplementation, emitFunctionDefinitions, emitFunctionCalls
- CompoundNode: initialize, emitFunctionDefinition, emitFunctionCall
- Add GpuTimerQuery helper class and getCurrentTimeNs() for GPU timing
  via GL_TIME_ELAPSED queries (guarded by MATERIALX_BUILD_TRACING)
- Add multi-frame render loop using framesPerMaterial for statistical
  validity, emitting MX_TRACE_ASYNC events on the GPU track
- Replace stale Cat:: alias with mx::Tracing::Category:: (the alias
  was removed in PR AcademySoftwareFoundation#2742)
Shader codegen source files (ShaderGraph.cpp, ShaderGenerator.cpp, etc.)
include MaterialXTrace/Tracing.h and use MX_TRACE macros. When Perfetto
tracing is enabled, MaterialXGenShader needs to link against MaterialXTrace
for the trace event symbols.
The CMake flag was renamed from MATERIALX_BUILD_TRACING to
MATERIALX_BUILD_PERFETTO_TRACING in PR AcademySoftwareFoundation#2742. Update all #ifdef
guards in RenderGlsl.cpp to match.
Port AsyncTrack enum, Sink::asyncEvent(), and MX_TRACE_ASYNC macro
from the pre-merge proto2 branch. This enables GPU timer query results
to be emitted as events on a dedicated "GPU" track in Perfetto traces.

Use std::numeric_limits<uint64_t>::max() for the GPU track ID to
guarantee no collision with OS thread IDs.
The previous commit accidentally set enableTracing to false, which
would prevent CI from producing Perfetto traces. Restore to true
to match the behavior established in PR AcademySoftwareFoundation#2742.
Without matplotlib, the HTML reports are generated with no charts,
making them essentially empty. Fail early with a clear install
message, consistent with how perfetto and pandas are handled.
Comment on lines +4 to +15
set(GENSHADER_MTLX_MODULES MaterialXFormat MaterialXCore)
if(MATERIALX_BUILD_PERFETTO_TRACING)
list(APPEND GENSHADER_MTLX_MODULES MaterialXTrace)
endif()

mx_add_library(MaterialXGenShader
SOURCE_FILES
${materialx_source}
HEADER_FILES
${materialx_headers}
MTLX_MODULES
MaterialXFormat
MaterialXCore
${GENSHADER_MTLX_MODULES}
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Adding the dependency to use instrumentation in this module.

Derive display labels from the actual directory names passed on the
command line, matching the convention already used by diff_traces.py.
Affects console output, HTML report title, and per-image labels.

Assisted-by: Claude (Anthropic) via Cursor IDE
Signed-off-by: Pavlo Penenko <pavlo.penenko@autodesk.com>
Use the shared openReport() from _report.py, matching the behavior
already present in diff_traces.py and diff_shaders.py.

Assisted-by: Claude (Anthropic) via Cursor IDE
Signed-off-by: Pavlo Penenko <pavlo.penenko@autodesk.com>
Use the same relative/fallback import pattern as diff_traces.py and
diff_shaders.py so the script works both as a package and standalone.

Assisted-by: Claude (Anthropic) via Cursor IDE
Signed-off-by: Pavlo Penenko <pavlo.penenko@autodesk.com>
@ppenenko ppenenko marked this pull request as ready for review February 18, 2026 22:02
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.

1 participant