diff --git a/.gitignore b/.gitignore index 880bacbffa..4e17dc323b 100644 --- a/.gitignore +++ b/.gitignore @@ -277,6 +277,8 @@ thirdparty/swappy-frame-pacing/armeabi-v7a/abi.json thirdparty/swappy-frame-pacing/x86/abi.json thirdparty/swappy-frame-pacing/x86_64/abi.json +thirdparty/perfetto/ + # Visual Studio 2015/2017 cache/options directory .vs/ diff --git a/core/profiling/SCsub b/core/profiling/SCsub index ac81fd67dc..f9084449b9 100644 --- a/core/profiling/SCsub +++ b/core/profiling/SCsub @@ -11,10 +11,12 @@ Import("env") env.add_source_files(env.core_sources, "*.cpp") +default_perfetto_install_dir = "../../thirdparty/perfetto" + def find_perfetto_path(path: pathlib.Path) -> pathlib.Path: if not path.is_dir(): - print("profiler_path must be empty or point to a directory.") + print(f"Perfetto profiler path '{path.absolute()}' is invalid.") Exit(255) if (path / "sdk" / "perfetto.cc").is_file(): @@ -24,7 +26,7 @@ def find_perfetto_path(path: pathlib.Path) -> pathlib.Path: # perfetto sdk directory. return path - print("Invalid profiler_path. Unable to find perfetto.cc.") + print("Invalid perfetto profiler path. Unable to find perfetto.cc.") Exit(255) @@ -76,10 +78,14 @@ if env["profiler"]: env_tracy.disable_warnings() env_tracy.add_source_files(env.core_sources, str((profiler_path / "TracyClient.cpp").absolute())) elif env["profiler"] == "perfetto": - if not env["profiler_path"]: - print("profiler_path must be set when using the perfetto profiler. Aborting.") + if env["profiler_path"]: + profiler_path = find_perfetto_path(pathlib.Path(env["profiler_path"])) + elif (default_perfetto_path := pathlib.Path(default_perfetto_install_dir)).is_dir(): + profiler_path = find_perfetto_path(default_perfetto_path) + else: + print("Perfetto must be installed or profiler_path must be set when using the perfetto profiler. Aborting.") Exit(255) - profiler_path = find_perfetto_path(pathlib.Path(env["profiler_path"])) + env.Prepend(CPPPATH=[str(profiler_path.absolute())]) env_perfetto = env.Clone() diff --git a/misc/scripts/install_perfetto.py b/misc/scripts/install_perfetto.py new file mode 100755 index 0000000000..cbe2b6d8f0 --- /dev/null +++ b/misc/scripts/install_perfetto.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +import os +import sys +import tempfile +import urllib.request +from zipfile import ZipFile + +sys.path.insert(0, os.path.join(os.path.dirname(os.path.abspath(__file__)), "../../")) + +from misc.utility.color import Ansi, color_print + + +def get_latest_tag(): + import json + + url = "https://api.github.com/repos/google/perfetto/releases/latest" + with urllib.request.urlopen(url) as response: + data = json.load(response) + return data["tag_name"] + + +# Perfetto +# Check for latest version: https://github.com/google/perfetto/releases/latest +perfetto_tag = get_latest_tag() +perfetto_filename = "perfetto-cpp-sdk-src.zip" +perfetto_folder = "thirdparty/perfetto" + +perfetto_archive_destination = os.path.join(tempfile.gettempdir(), perfetto_filename) + +if os.path.isfile(perfetto_archive_destination): + os.remove(perfetto_archive_destination) + +print(f"Downloading Perfetto {perfetto_tag} ...") +urllib.request.urlretrieve( + f"https://github.com/google/perfetto/releases/download/{perfetto_tag}/{perfetto_filename}", + perfetto_archive_destination, +) + +print(f"Extracting Perfetto {perfetto_tag} to {perfetto_folder} ...") +with ZipFile(perfetto_archive_destination, "r") as zip_file: + zip_file.extractall(perfetto_folder) +os.remove(perfetto_archive_destination) +print("Perfetto installed successfully.\n") + +# Complete message +color_print(f'{Ansi.GREEN}Perfetto was installed to "{perfetto_folder}" successfully!') diff --git a/platform/android/detect.py b/platform/android/detect.py index 2b3b359d24..fff6944cf7 100644 --- a/platform/android/detect.py +++ b/platform/android/detect.py @@ -114,6 +114,21 @@ def detect_swappy(): return has_swappy +def should_enable_perfetto(env: "SConsEnvironment"): + from SCons.Script import ARGUMENTS + + cmdline_val = ARGUMENTS.get("profiler") + if cmdline_val is not None: + return cmdline_val == "perfetto" + elif env.debug_features and not (env["store_release"]) and not (env["production"]): + return True + return False + + +def detect_perfetto(): + return os.path.exists("thirdparty/perfetto") + + def configure(env: "SConsEnvironment"): # Validate arch. supported_arches = ["x86_32", "x86_64", "arm32", "arm64"] @@ -188,6 +203,16 @@ def configure(env: "SConsEnvironment"): CCFLAGS=(["-fpic", "-ffunction-sections", "-funwind-tables", "-fstack-protector-strong", "-fvisibility=hidden"]) ) + if should_enable_perfetto(env): + has_perfetto = detect_perfetto() + if not has_perfetto: + print_warning( + f"Perfetto not detected! It is recommended you run `python {os.path.join('misc', 'scripts', 'install_perfetto.py')}` to download and install Perfetto before compiling.\n" + ) + else: + env["profiler"] = "perfetto" + env["profiler_path"] = os.path.abspath("thirdparty/perfetto") + has_swappy = detect_swappy() if not has_swappy: print_warning( diff --git a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt index 0c3956841d..cf8aede69f 100644 --- a/platform/android/java/nativeSrcsConfigs/CMakeLists.txt +++ b/platform/android/java/nativeSrcsConfigs/CMakeLists.txt @@ -9,6 +9,7 @@ set(CMAKE_CXX_EXTENSIONS OFF) set(GODOT_ROOT_DIR ../../../..) set(ANDROID_ROOT_DIR "${GODOT_ROOT_DIR}/platform/android" CACHE STRING "") set(OPENXR_INCLUDE_DIR "${GODOT_ROOT_DIR}/thirdparty/openxr/include" CACHE STRING "") +set(PERFETTO_INCLUDE_DIR "${GODOT_ROOT_DIR}/thirdparty/perfetto" CACHE STRING "") # Get sources file(GLOB_RECURSE SOURCES ${GODOT_ROOT_DIR}/*.c**) @@ -19,7 +20,8 @@ target_include_directories(${PROJECT_NAME} SYSTEM PUBLIC ${GODOT_ROOT_DIR} ${ANDROID_ROOT_DIR} - ${OPENXR_INCLUDE_DIR}) + ${OPENXR_INCLUDE_DIR} + ${PERFETTO_INCLUDE_DIR}) add_definitions( -DUNIX_ENABLED @@ -29,4 +31,5 @@ add_definitions( -DTOOLS_ENABLED -DDEBUG_ENABLED -DRD_ENABLED + -DGODOT_USE_PERFETTO )