110 lines
4.3 KiB
Python
110 lines
4.3 KiB
Python
#!/usr/bin/env python3
|
|
"""Validate Agrarian Unreal stat and Insights profiling markers."""
|
|
|
|
from pathlib import Path
|
|
import sys
|
|
|
|
REPO_ROOT = Path(__file__).resolve().parents[1]
|
|
|
|
STATS = [
|
|
"STAT_AgrarianGameStateTick",
|
|
"STAT_AgrarianSurvivalTick",
|
|
"STAT_AgrarianSkyLightingRefresh",
|
|
"STAT_AgrarianWeatherAudioRefresh",
|
|
"STAT_AgrarianFoliageInstanceMutation",
|
|
"STAT_AgrarianWeatherProviderRequest",
|
|
"STAT_AgrarianWeatherProviderParse",
|
|
]
|
|
|
|
SOURCE_MARKERS = {
|
|
"Source/AgrarianGame/AgrarianGameState.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianGameStateTick)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianGameStateTick)",
|
|
],
|
|
"Source/AgrarianGame/AgrarianSurvivalComponent.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianSurvivalTick)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianSurvivalTick)",
|
|
],
|
|
"Source/AgrarianGame/AgrarianSkyLightingController.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianSkyLightingRefresh)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianSkyLightingRefresh)",
|
|
],
|
|
"Source/AgrarianGame/AgrarianWeatherAudioController.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherAudioRefresh)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherAudioRefresh)",
|
|
],
|
|
"Source/AgrarianGame/AgrarianFoliagePatch.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageClear)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddTreeInstance)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddShrubInstance)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianFoliageAddGrassInstance)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianFoliageInstanceMutation)",
|
|
],
|
|
"Source/AgrarianGame/AgrarianWeatherProviderSubsystem.cpp": [
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderRequest)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderFallback)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderParseOpenMeteo)",
|
|
"TRACE_CPUPROFILER_EVENT_SCOPE(AgrarianWeatherProviderParseNoaaNws)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherProviderRequest)",
|
|
"SCOPE_CYCLE_COUNTER(STAT_AgrarianWeatherProviderParse)",
|
|
],
|
|
}
|
|
|
|
|
|
def read_text(relative_path: str) -> str:
|
|
path = REPO_ROOT / relative_path
|
|
if not path.exists():
|
|
raise AssertionError(f"Missing required file: {relative_path}")
|
|
return path.read_text(encoding="utf-8")
|
|
|
|
|
|
def require(needle: str, haystack: str, context: str) -> None:
|
|
if needle not in haystack:
|
|
raise AssertionError(f"Missing {needle!r} in {context}")
|
|
|
|
|
|
def main() -> int:
|
|
errors: list[str] = []
|
|
|
|
try:
|
|
header = read_text("Source/AgrarianGame/AgrarianPerformanceStats.h")
|
|
source = read_text("Source/AgrarianGame/AgrarianPerformanceStats.cpp")
|
|
require("DECLARE_STATS_GROUP(TEXT(\"Agrarian\"), STATGROUP_Agrarian", header, "AgrarianPerformanceStats.h")
|
|
for stat in STATS:
|
|
require(f"DECLARE_CYCLE_STAT_EXTERN(", header, "AgrarianPerformanceStats.h")
|
|
require(stat, header, "AgrarianPerformanceStats.h")
|
|
require(f"DEFINE_STAT({stat});", source, "AgrarianPerformanceStats.cpp")
|
|
except AssertionError as exc:
|
|
errors.append(str(exc))
|
|
|
|
for relative_path, markers in SOURCE_MARKERS.items():
|
|
try:
|
|
contents = read_text(relative_path)
|
|
require("#include \"AgrarianPerformanceStats.h\"", contents, relative_path)
|
|
require("#include \"ProfilingDebugging/CpuProfilerTrace.h\"", contents, relative_path)
|
|
for marker in markers:
|
|
require(marker, contents, relative_path)
|
|
except AssertionError as exc:
|
|
errors.append(str(exc))
|
|
|
|
try:
|
|
roadmap = read_text("AGRARIAN_DEVELOPMENT_ROADMAP.md")
|
|
require("[x] Add performance profiling markers.", roadmap, "AGRARIAN_DEVELOPMENT_ROADMAP.md")
|
|
docs = read_text("Docs/TechnicalDesignDocument.md")
|
|
require("stat Agrarian", docs, "Docs/TechnicalDesignDocument.md")
|
|
require("Unreal Insights", docs, "Docs/TechnicalDesignDocument.md")
|
|
except AssertionError as exc:
|
|
errors.append(str(exc))
|
|
|
|
if errors:
|
|
for error in errors:
|
|
print(f"ERROR: {error}", file=sys.stderr)
|
|
return 1
|
|
|
|
print("Performance profiling markers are wired.")
|
|
return 0
|
|
|
|
|
|
if __name__ == "__main__":
|
|
raise SystemExit(main())
|