├── Plugins ├── iOS │ ├── libKLab_Profiling.a │ └── libKLab_Profiling.a.meta ├── Linux │ ├── x64 │ │ ├── libKLab_Profiling.so │ │ └── libKLab_Profiling.so.meta │ └── x64.meta ├── Windows │ ├── x64 │ │ ├── KLab_Profiling.dll │ │ ├── KLab_Profiling.exp │ │ ├── KLab_Profiling.lib │ │ ├── KLab_Profiling.exp.meta │ │ ├── KLab_Profiling.lib.meta │ │ ├── KLab_Profiling.dll.manifest.meta │ │ ├── KLab_Profiling.dll.manifest │ │ └── KLab_Profiling.dll.meta │ └── x64.meta ├── Android │ ├── x86 │ │ ├── libKLab_Profiling.so │ │ └── libKLab_Profiling.so.meta │ ├── arm64-v8a │ │ ├── libKLab_Profiling.so │ │ └── libKLab_Profiling.so.meta │ ├── armeabi-v7a │ │ ├── libKLab_Profiling.so │ │ └── libKLab_Profiling.so.meta │ ├── x86.meta │ ├── arm64-v8a.meta │ └── armeabi-v7a.meta ├── MacOS │ ├── KLab_Profiling.bundle │ │ ├── Contents │ │ │ ├── MacOS │ │ │ │ ├── KLab_Profiling │ │ │ │ └── KLab_Profiling.meta │ │ │ ├── Info.plist.meta │ │ │ ├── MacOS.meta │ │ │ └── Info.plist │ │ └── Contents.meta │ └── KLab_Profiling.bundle.meta ├── Linux.meta ├── MacOS.meta ├── iOS.meta ├── Android.meta └── Windows.meta ├── Plugins~ ├── Vendor │ ├── ios-cmake │ │ └── .placeholder │ └── UnityPluginApi │ │ └── .placeholder ├── SourceFiles │ ├── ExternTrace.cpp │ ├── PluginContext.cpp │ ├── ATrace.cpp │ ├── Utils.cpp │ ├── CSharpTrace.cpp │ └── Plugin.cpp ├── BuildScripts │ ├── BuildMacOS.sh │ ├── BuildLinux.sh │ ├── BuildIOS.sh │ ├── BuildWindows.bat │ └── BuildAndroid.bat ├── CMakeLists.txt ├── Include │ └── KLab │ │ ├── Profiling.hpp │ │ └── Profiling │ │ └── CSharpInterface.h └── Internal │ └── KLab │ └── Profiling │ └── Internal.hpp ├── LICENSE.meta ├── README.md.meta ├── package.json.meta ├── Plugins.meta ├── Runtime.meta ├── Tests.meta ├── Runtime ├── KLab.meta ├── KLab.Profiling.asmdef.meta ├── KLab.Profiling.asmdef └── KLab │ ├── Profiling.meta │ └── Profiling │ ├── LowLevel.meta │ ├── PluginDriver.cs.meta │ ├── PluginInfo.cs.meta │ ├── LowLevel │ ├── ErrorCode.cs.meta │ ├── TraceUtility.cs.meta │ ├── ErrorCode.cs │ └── TraceUtility.cs │ ├── PluginInfo.cs │ └── PluginDriver.cs ├── Tests ├── KLab.meta ├── KLab.Profiling.Tests.asmdef.meta ├── KLab │ ├── Profiling.meta │ └── Profiling │ │ ├── Tests.meta │ │ └── Tests │ │ ├── LowLevel.meta │ │ └── LowLevel │ │ ├── TraceUtilityTests.cs.meta │ │ └── TraceUtilityTests.cs └── KLab.Profiling.Tests.asmdef ├── package.json ├── .gitignore ├── LICENSE └── README.md /Plugins/iOS/libKLab_Profiling.a: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/iOS/libKLab_Profiling.a -------------------------------------------------------------------------------- /Plugins/Linux/x64/libKLab_Profiling.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Linux/x64/libKLab_Profiling.so -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Windows/x64/KLab_Profiling.dll -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.exp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Windows/x64/KLab_Profiling.exp -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.lib: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Windows/x64/KLab_Profiling.lib -------------------------------------------------------------------------------- /Plugins/Android/x86/libKLab_Profiling.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Android/x86/libKLab_Profiling.so -------------------------------------------------------------------------------- /Plugins~/Vendor/ios-cmake/.placeholder: -------------------------------------------------------------------------------- 1 | Clone (or download) 'ios-cmake' (https://github.com/leetal/ios-cmake) into this folder to build iOS libraries -------------------------------------------------------------------------------- /Plugins/Android/arm64-v8a/libKLab_Profiling.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Android/arm64-v8a/libKLab_Profiling.so -------------------------------------------------------------------------------- /Plugins/Android/armeabi-v7a/libKLab_Profiling.so: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/Android/armeabi-v7a/libKLab_Profiling.so -------------------------------------------------------------------------------- /Plugins~/Vendor/UnityPluginApi/.placeholder: -------------------------------------------------------------------------------- 1 | Copy Unity Plugin API headers into this folder 2 | unless environment variable 'UNITY_PLUGIN_API_ROOT' points to Unity plugin API folder 3 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents/MacOS/KLab_Profiling: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KLab/klab-profiling-unity/HEAD/Plugins/MacOS/KLab_Profiling.bundle/Contents/MacOS/KLab_Profiling -------------------------------------------------------------------------------- /LICENSE.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 77064e15420cb2046aa0edae0b77cccb 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /README.md.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cbd40f0830047014fa11ae39a8b9dc5b 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /package.json.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 0b2f2621ed006c64184834c2051b6883 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 43354b6ec879ecc48a837539c1ba5300 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b16008520c78684cb53effa2757d521 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 4ab93e18add16da45a38b4c1cff205d0 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Linux.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c2d2746107f9e734a870695e5d51467e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/MacOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 56c393911b2c11447bd25b0385eadda4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/iOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c5da9147e2c33cb46adf6e3ad5043e79 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Runtime/KLab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e86a0b20c250b7c41a3d2ba91e32f566 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/KLab.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3a4c814d5fc0dc7458bcf182b13393d4 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Android.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 14ebe78d02241d64d9d352799749c7b6 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Linux/x64.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 16d188ec7763f2844bedbcc42c86a28a 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Windows.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 90a009e033fcda94a9a7ee59d116cc7f 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Windows/x64.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7a7caa394e4cf0d4e8c481231032c14d 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.exp.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 85d39bc850a101944913fad3ad7a0454 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.lib.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c21369d33492447438ffa4669dd15cd4 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/KLab.Profiling.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 736f068af107e5a4b80ccfa39e76e79a 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/KLab.Profiling.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KLab.Profiling", 3 | "references": [], 4 | "optionalUnityReferences": [], 5 | "includePlatforms": [], 6 | "excludePlatforms": [], 7 | "allowUnsafeCode": true 8 | } -------------------------------------------------------------------------------- /Runtime/KLab/Profiling.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 245506b6bbc007d498093d791a452185 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/KLab.Profiling.Tests.asmdef.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 924949057deb8d843987008680b50186 3 | AssemblyDefinitionImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/KLab/Profiling.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 7ed48b372b43c3e4a9e264247b80c3bd 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.dll.manifest.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 23f6aef786b98dc40ab542974a156886 3 | TextScriptImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Tests/KLab/Profiling/Tests.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 2a0531f8abf683746b80ee97de1699d2 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "com.klab.profiling", 3 | "description": "Helper library for profiling Unity projects", 4 | "version": "1.1.0-preview", 5 | "unity": "2018.2", 6 | "displayName": "KLab Profiling" 7 | } 8 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents/Info.plist.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 786b10fa50254f34680f1a3ac50a81f6 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/LowLevel.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bab764401980bf04d97de1e3a45772d7 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/KLab/Profiling/Tests/LowLevel.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 8819a81f246baf847a38eb1a550357ea 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 9bd2519dc63f80444a6770a18213df0e 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents/MacOS/KLab_Profiling.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 5b36d46db4f70374faf08b23fe804690 3 | DefaultImporter: 4 | externalObjects: {} 5 | userData: 6 | assetBundleName: 7 | assetBundleVariant: 8 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents/MacOS.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e1dd9dca2bec3b544a4868e8fbc954ab 3 | folderAsset: yes 4 | DefaultImporter: 5 | externalObjects: {} 6 | userData: 7 | assetBundleName: 8 | assetBundleVariant: 9 | -------------------------------------------------------------------------------- /Tests/KLab.Profiling.Tests.asmdef: -------------------------------------------------------------------------------- 1 | { 2 | "name": "KLab.Profiling.Tests", 3 | "references": [ 4 | "KLab.Profiling" 5 | ], 6 | "optionalUnityReferences": [ 7 | "TestAssemblies" 8 | ], 9 | "includePlatforms": [], 10 | "excludePlatforms": [], 11 | "allowUnsafeCode": true 12 | } -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/PluginDriver.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 54494e12107ade74a8e1f21503475593 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/PluginInfo.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 05aac9a8b866d50458042b2008515834 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/LowLevel/ErrorCode.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: db1a0ddc07c624e48b1833e35234bc06 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/LowLevel/TraceUtility.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 86c3fa757b57f644aba0a2a2ab80f756 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Tests/KLab/Profiling/Tests/LowLevel/TraceUtilityTests.cs.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 26542b84f0650b640ae127b87601d899 3 | MonoImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | defaultReferences: [] 7 | executionOrder: 0 8 | icon: {instanceID: 0} 9 | userData: 10 | assetBundleName: 11 | assetBundleVariant: 12 | -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.dll.manifest: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | !/.gitignore 4 | !/KLab.meta 5 | !/LICENSE 6 | !/LICENSE.meta 7 | !/package.json 8 | !/package.json.meta 9 | !/Plugins.meta 10 | !/README.md 11 | !/README.md.meta 12 | !/Runtime.meta 13 | !/Tests.meta 14 | 15 | !/Plugins~/ 16 | /Plugins~/* 17 | !/Plugins~/BuildScripts/ 18 | !/Plugins~/Include/ 19 | !/Plugins~/Internal/ 20 | !/Plugins~/SourceFiles/ 21 | !/Plugins~/Vendor/ 22 | /Plugins~/Vendor/ios-cmake/* 23 | !/Plugins~/Vendor/ios-cmake/.placeholder 24 | /Plugins~/Vendor/UnityPluginApi/* 25 | !/Plugins~/Vendor/UnityPluginApi/.placeholder 26 | !/Plugins~/CMakeLists.txt 27 | !/Plugins/ 28 | !/Runtime/ 29 | !/Tests/ 30 | -------------------------------------------------------------------------------- /Plugins/Android/x86.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 3963573e4671a8c4a8fe4e43419304ce 3 | folderAsset: yes 4 | PluginImporter: 5 | externalObjects: {} 6 | serializedVersion: 2 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | isOverridable: 0 11 | platformData: 12 | - first: 13 | Android: Android 14 | second: 15 | enabled: 1 16 | settings: {} 17 | - first: 18 | Any: 19 | second: 20 | enabled: 0 21 | settings: {} 22 | - first: 23 | Editor: Editor 24 | second: 25 | enabled: 0 26 | settings: 27 | DefaultValueInitialized: true 28 | userData: 29 | assetBundleName: 30 | assetBundleVariant: 31 | -------------------------------------------------------------------------------- /Plugins/Android/arm64-v8a.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: e3959a90541c7f44899207145b838121 3 | folderAsset: yes 4 | PluginImporter: 5 | externalObjects: {} 6 | serializedVersion: 2 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | isOverridable: 0 11 | platformData: 12 | - first: 13 | Android: Android 14 | second: 15 | enabled: 1 16 | settings: {} 17 | - first: 18 | Any: 19 | second: 20 | enabled: 0 21 | settings: {} 22 | - first: 23 | Editor: Editor 24 | second: 25 | enabled: 0 26 | settings: 27 | DefaultValueInitialized: true 28 | userData: 29 | assetBundleName: 30 | assetBundleVariant: 31 | -------------------------------------------------------------------------------- /Plugins/Android/armeabi-v7a.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: b60ee590d66d473499fd7e6d0ce882f5 3 | folderAsset: yes 4 | PluginImporter: 5 | externalObjects: {} 6 | serializedVersion: 2 7 | iconMap: {} 8 | executionOrder: {} 9 | isPreloaded: 0 10 | isOverridable: 0 11 | platformData: 12 | - first: 13 | Android: Android 14 | second: 15 | enabled: 1 16 | settings: {} 17 | - first: 18 | Any: 19 | second: 20 | enabled: 0 21 | settings: {} 22 | - first: 23 | Editor: Editor 24 | second: 25 | enabled: 0 26 | settings: 27 | DefaultValueInitialized: true 28 | userData: 29 | assetBundleName: 30 | assetBundleVariant: 31 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/ExternTrace.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // ----------- // 10 | // PLUGIN INFO // 11 | // ----------- // 12 | 13 | int32_t KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_PluginInfo_SupportsExternTrace() 14 | { 15 | return (KLab::Profiling::Trace::TryGetExternTrace() != nullptr ); 16 | } 17 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle/Contents/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | English 7 | CFBundleExecutable 8 | KLab_Profiling 9 | CFBundleGetInfoString 10 | 11 | CFBundleIconFile 12 | 13 | CFBundleIdentifier 14 | 15 | CFBundleInfoDictionaryVersion 16 | 6.0 17 | CFBundleLongVersionString 18 | 19 | CFBundleName 20 | 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 29 | CSResourcesFileMapped 30 | 31 | NSHumanReadableCopyright 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 KLab Inc.. http://www.klab.com/jp/ 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/LowLevel/ErrorCode.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | namespace KLab.Profiling.LowLevel 7 | { 8 | /// 9 | /// Error code 10 | /// 11 | public enum ErrorCode : int 12 | { 13 | /// 14 | /// No error 15 | /// 16 | NoError = 0, 17 | 18 | /// 19 | /// Unavailable functionality requested 20 | /// 21 | NotAvailable = -1, 22 | 23 | /// 24 | /// One or more arguments have been invailed 25 | /// 26 | InvalidArgument = -2, 27 | 28 | /// 29 | /// One or more states have been invailed for operation 30 | /// 31 | InvalidState = -3 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /Plugins~/BuildScripts/BuildMacOS.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | 3 | # Builds libraries for macOS 4 | echo -- macOS plugin build 5 | 6 | 7 | # Initialize arguments 8 | BuildScriptsDirectory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 9 | PluginDirectory="$BuildScriptsDirectory/.." 10 | TempDirectory="$PluginDirectory/.temp" 11 | BuildDirectory="$PluginDirectory/../Plugins/MacOS" 12 | UnityPluginApiDirectory="$UNITY_PLUGIN_API_ROOT" 13 | 14 | BuildType="Release" 15 | 16 | 17 | # Parse command line options 18 | echo 19 | echo 20 | echo [User Options] 21 | 22 | 23 | for arg in "$0" 24 | do 25 | if [ "arg" = "--debug" ]; then 26 | BuildType="Debug" 27 | fi 28 | done 29 | 30 | 31 | if [ "$BuildType" = "Release" ]; then 32 | echo -- Build \'$BuildType\' \(pass \'--debug\' on command line for debug build\) 33 | else 34 | echo -- Build \'$BuildType\' 35 | fi 36 | 37 | 38 | # Try locate Unity API relatively 39 | if [ ! -d "$UnityPluginApiDirectory" ]; then 40 | UnityPluginApiDirectory="$PluginDirectory/Vendor/UnityPluginApi" 41 | fi 42 | 43 | 44 | # Validate 45 | echo 46 | echo 47 | echo [Validation] 48 | 49 | if [ -f "$UnityPluginApiDirectory/IUnityInterface.h" ]; then 50 | echo -- Unity Plugin API found 51 | else 52 | echo -- \[ERROR\] Unity Plugin API not found 53 | echo " ('UNITY_PLUGIN_API_ROOT' environment variable or header files in './Plugin~/Vendor/UnityPluginApi' expected)" 54 | 55 | exit -1 56 | fi 57 | 58 | 59 | # Clear temp 60 | if [ -d "$TempDirectory" ]; then 61 | rm -rf "$TempDirectory" 62 | fi 63 | 64 | 65 | # Build binary 66 | echo 67 | echo 68 | echo [Bundle Build] 69 | 70 | mkdir $TempDirectory 71 | 72 | cd $TempDirectory 73 | cmake "$PluginDirectory" -G"Unix Makefiles" -DCMAKE_BUILD_TYPE="$BuildType" -DKLAB_PROFILING_UNITY_PLUGIN_API_PATH="$UnityPluginApiDirectory" -DKLAB_PROFILING_OUTPUT_DIRECTORY="$BuildDirectory" 74 | make 75 | cd .. 76 | 77 | rm -rf "$TempDirectory" 78 | -------------------------------------------------------------------------------- /Plugins~/BuildScripts/BuildLinux.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | 3 | # Builds libraries for Linux 4 | echo -- Linux plugin build 5 | 6 | 7 | # Initialize arguments 8 | BuildScriptsDirectory="$(dirname $(readlink -f $0))" 9 | PluginDirectory="$BuildScriptsDirectory/.." 10 | TempDirectory="$PluginDirectory/.temp" 11 | BuildDirectory="$PluginDirectory/../Plugins/Linux" 12 | UnityPluginApiDirectory="$UNITY_PLUGIN_API_ROOT" 13 | 14 | BuildType="Release" 15 | Abi="x86" 16 | echo $BuildScriptsDirectory 17 | if [ $(uname -m) = "x86_64" ]; then 18 | Abi="x64" 19 | fi 20 | 21 | 22 | # Parse command line options 23 | echo 24 | echo 25 | echo [User Options] 26 | 27 | 28 | for arg in "$0" 29 | do 30 | if [ "arg" = "--debug" ]; then 31 | BuildType="Debug" 32 | fi 33 | done 34 | 35 | 36 | if [ "$BuildType" = "Release" ]; then 37 | echo -- Build \'$BuildType\' \(pass \'--debug\' on command line for debug build\) 38 | else 39 | echo -- Build \'$BuildType\' 40 | fi 41 | 42 | 43 | # Try locate Unity API relatively 44 | if [ ! -d "$UnityPluginApiDirectory" ]; then 45 | UnityPluginApiDirectory="$PluginDirectory/Vendor/UnityPluginApi" 46 | fi 47 | 48 | 49 | # Validate 50 | echo 51 | echo 52 | echo [Validation] 53 | echo $UnityPluginApiDirectory 54 | if [ -f "$UnityPluginApiDirectory/IUnityInterface.h" ]; then 55 | echo -- Unity Plugin API found 56 | else 57 | echo -- \[ERROR\] Unity Plugin API not found 58 | echo " ('UNITY_PLUGIN_API_ROOT' environment variable or header files in './Plugin~/Vendor/UnityPluginApi' expected)" 59 | 60 | exit 1 61 | fi 62 | 63 | 64 | # Clear temp 65 | if [ -d "$TempDirectory" ]; then 66 | rm -rf "$TempDirectory" 67 | fi 68 | 69 | 70 | # Build binary 71 | echo 72 | echo 73 | echo [$Abi Build] 74 | 75 | mkdir $TempDirectory 76 | 77 | cd $TempDirectory 78 | cmake "$PluginDirectory" -G"Unix Makefiles" -DCMAKE_BUILD_TYPE="$BuildType" -DKLAB_PROFILING_UNITY_PLUGIN_API_PATH="$UnityPluginApiDirectory" -DKLAB_PROFILING_OUTPUT_DIRECTORY="$BuildDirectory/$Abi" 79 | make 80 | cd .. 81 | 82 | rm -rf "$TempDirectory" 83 | -------------------------------------------------------------------------------- /Plugins/Android/x86/libKLab_Profiling.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 069e972cc24d74048b4649ba017ebbef 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | isPreloaded: 0 9 | isOverridable: 0 10 | platformData: 11 | - first: 12 | '': Any 13 | second: 14 | enabled: 0 15 | settings: 16 | Exclude Android: 0 17 | Exclude Editor: 1 18 | Exclude Linux: 1 19 | Exclude Linux64: 1 20 | Exclude LinuxUniversal: 1 21 | Exclude OSXUniversal: 1 22 | Exclude Win: 1 23 | Exclude Win64: 1 24 | - first: 25 | Android: Android 26 | second: 27 | enabled: 1 28 | settings: 29 | CPU: x86 30 | - first: 31 | Any: 32 | second: 33 | enabled: 0 34 | settings: {} 35 | - first: 36 | Editor: Editor 37 | second: 38 | enabled: 0 39 | settings: 40 | CPU: AnyCPU 41 | DefaultValueInitialized: true 42 | OS: AnyOS 43 | - first: 44 | Facebook: Win 45 | second: 46 | enabled: 0 47 | settings: 48 | CPU: AnyCPU 49 | - first: 50 | Facebook: Win64 51 | second: 52 | enabled: 0 53 | settings: 54 | CPU: AnyCPU 55 | - first: 56 | Standalone: Linux 57 | second: 58 | enabled: 0 59 | settings: 60 | CPU: x86 61 | - first: 62 | Standalone: Linux64 63 | second: 64 | enabled: 0 65 | settings: 66 | CPU: x86_64 67 | - first: 68 | Standalone: LinuxUniversal 69 | second: 70 | enabled: 0 71 | settings: 72 | CPU: None 73 | - first: 74 | Standalone: OSXUniversal 75 | second: 76 | enabled: 0 77 | settings: 78 | CPU: AnyCPU 79 | - first: 80 | Standalone: Win 81 | second: 82 | enabled: 0 83 | settings: 84 | CPU: AnyCPU 85 | - first: 86 | Standalone: Win64 87 | second: 88 | enabled: 0 89 | settings: 90 | CPU: AnyCPU 91 | userData: 92 | assetBundleName: 93 | assetBundleVariant: 94 | -------------------------------------------------------------------------------- /Plugins/Windows/x64/KLab_Profiling.dll.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: c89c2ea6163bde842821deb35a5e8e7a 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | isPreloaded: 0 9 | isOverridable: 0 10 | platformData: 11 | - first: 12 | '': Any 13 | second: 14 | enabled: 0 15 | settings: 16 | Exclude Android: 1 17 | Exclude Editor: 0 18 | Exclude Linux: 0 19 | Exclude Linux64: 0 20 | Exclude LinuxUniversal: 0 21 | Exclude OSXUniversal: 0 22 | Exclude Win: 1 23 | Exclude Win64: 0 24 | - first: 25 | Android: Android 26 | second: 27 | enabled: 0 28 | settings: 29 | CPU: ARMv7 30 | - first: 31 | Any: 32 | second: 33 | enabled: 0 34 | settings: {} 35 | - first: 36 | Editor: Editor 37 | second: 38 | enabled: 1 39 | settings: 40 | CPU: x86_64 41 | DefaultValueInitialized: true 42 | OS: Windows 43 | - first: 44 | Facebook: Win 45 | second: 46 | enabled: 0 47 | settings: 48 | CPU: None 49 | - first: 50 | Facebook: Win64 51 | second: 52 | enabled: 0 53 | settings: 54 | CPU: AnyCPU 55 | - first: 56 | Standalone: Linux 57 | second: 58 | enabled: 1 59 | settings: 60 | CPU: x86 61 | - first: 62 | Standalone: Linux64 63 | second: 64 | enabled: 1 65 | settings: 66 | CPU: x86_64 67 | - first: 68 | Standalone: LinuxUniversal 69 | second: 70 | enabled: 1 71 | settings: 72 | CPU: AnyCPU 73 | - first: 74 | Standalone: OSXUniversal 75 | second: 76 | enabled: 1 77 | settings: 78 | CPU: AnyCPU 79 | - first: 80 | Standalone: Win 81 | second: 82 | enabled: 0 83 | settings: 84 | CPU: None 85 | - first: 86 | Standalone: Win64 87 | second: 88 | enabled: 1 89 | settings: 90 | CPU: AnyCPU 91 | userData: 92 | assetBundleName: 93 | assetBundleVariant: 94 | -------------------------------------------------------------------------------- /Plugins/Android/arm64-v8a/libKLab_Profiling.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: cc64baaa188ee9e43bfeb24a2e156f99 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | isPreloaded: 0 9 | isOverridable: 0 10 | platformData: 11 | - first: 12 | '': Any 13 | second: 14 | enabled: 0 15 | settings: 16 | Exclude Android: 0 17 | Exclude Editor: 1 18 | Exclude Linux: 1 19 | Exclude Linux64: 1 20 | Exclude LinuxUniversal: 1 21 | Exclude OSXUniversal: 1 22 | Exclude Win: 1 23 | Exclude Win64: 1 24 | - first: 25 | Android: Android 26 | second: 27 | enabled: 1 28 | settings: 29 | CPU: ARM64 30 | - first: 31 | Any: 32 | second: 33 | enabled: 0 34 | settings: {} 35 | - first: 36 | Editor: Editor 37 | second: 38 | enabled: 0 39 | settings: 40 | CPU: AnyCPU 41 | DefaultValueInitialized: true 42 | OS: AnyOS 43 | - first: 44 | Facebook: Win 45 | second: 46 | enabled: 0 47 | settings: 48 | CPU: AnyCPU 49 | - first: 50 | Facebook: Win64 51 | second: 52 | enabled: 0 53 | settings: 54 | CPU: AnyCPU 55 | - first: 56 | Standalone: Linux 57 | second: 58 | enabled: 0 59 | settings: 60 | CPU: None 61 | - first: 62 | Standalone: Linux64 63 | second: 64 | enabled: 0 65 | settings: 66 | CPU: None 67 | - first: 68 | Standalone: LinuxUniversal 69 | second: 70 | enabled: 0 71 | settings: 72 | CPU: None 73 | - first: 74 | Standalone: OSXUniversal 75 | second: 76 | enabled: 0 77 | settings: 78 | CPU: None 79 | - first: 80 | Standalone: Win 81 | second: 82 | enabled: 0 83 | settings: 84 | CPU: AnyCPU 85 | - first: 86 | Standalone: Win64 87 | second: 88 | enabled: 0 89 | settings: 90 | CPU: AnyCPU 91 | userData: 92 | assetBundleName: 93 | assetBundleVariant: 94 | -------------------------------------------------------------------------------- /Plugins/Android/armeabi-v7a/libKLab_Profiling.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: bcf5b16d6114b7648be51517f35ac71f 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | isPreloaded: 0 9 | isOverridable: 0 10 | platformData: 11 | - first: 12 | '': Any 13 | second: 14 | enabled: 0 15 | settings: 16 | Exclude Android: 0 17 | Exclude Editor: 1 18 | Exclude Linux: 1 19 | Exclude Linux64: 1 20 | Exclude LinuxUniversal: 1 21 | Exclude OSXUniversal: 1 22 | Exclude Win: 1 23 | Exclude Win64: 1 24 | - first: 25 | Android: Android 26 | second: 27 | enabled: 1 28 | settings: 29 | CPU: ARMv7 30 | - first: 31 | Any: 32 | second: 33 | enabled: 0 34 | settings: {} 35 | - first: 36 | Editor: Editor 37 | second: 38 | enabled: 0 39 | settings: 40 | CPU: AnyCPU 41 | DefaultValueInitialized: true 42 | OS: AnyOS 43 | - first: 44 | Facebook: Win 45 | second: 46 | enabled: 0 47 | settings: 48 | CPU: AnyCPU 49 | - first: 50 | Facebook: Win64 51 | second: 52 | enabled: 0 53 | settings: 54 | CPU: AnyCPU 55 | - first: 56 | Standalone: Linux 57 | second: 58 | enabled: 0 59 | settings: 60 | CPU: None 61 | - first: 62 | Standalone: Linux64 63 | second: 64 | enabled: 0 65 | settings: 66 | CPU: None 67 | - first: 68 | Standalone: LinuxUniversal 69 | second: 70 | enabled: 0 71 | settings: 72 | CPU: None 73 | - first: 74 | Standalone: OSXUniversal 75 | second: 76 | enabled: 0 77 | settings: 78 | CPU: None 79 | - first: 80 | Standalone: Win 81 | second: 82 | enabled: 0 83 | settings: 84 | CPU: AnyCPU 85 | - first: 86 | Standalone: Win64 87 | second: 88 | enabled: 0 89 | settings: 90 | CPU: AnyCPU 91 | userData: 92 | assetBundleName: 93 | assetBundleVariant: 94 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/PluginContext.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #include 14 | #include 15 | 16 | 17 | // -------------- // 18 | // PLUGIN CONTEXT // 19 | // -------------- // 20 | 21 | namespace KLab { namespace Profiling { namespace Plugin 22 | { 23 | void PluginContext::Unload() 24 | { 25 | if (!*this) 26 | { 27 | return; 28 | } 29 | 30 | 31 | if (Trace.ATrace) 32 | { 33 | Trace.ATrace->Unload(); 34 | } 35 | if (Trace.ExternTrace) 36 | { 37 | Trace.ExternTrace->Unload(); 38 | } 39 | Utils->Unload(); 40 | 41 | 42 | Unity.Interfaces = nullptr; 43 | } 44 | 45 | 46 | PluginContext &CreatePluginContext(IUnityInterfaces *unity) 47 | { 48 | auto &context = GetPluginContext(); 49 | 50 | 51 | // Don't re-initialize 52 | if (context) 53 | { 54 | return context; 55 | } 56 | 57 | 58 | context.Unity.Interfaces = unity; 59 | context.Unity.ProfilerCallbacks = unity->Get(); 60 | context.Trace.ATrace = KLab::Profiling::Trace::TryGetATrace(); 61 | context.Trace.CSharpTrace = &KLab::Profiling::Trace::GetCSharpTrace(); 62 | context.Trace.ExternTrace = KLab::Profiling::Trace::TryGetExternTrace(); 63 | context.Utils = &KLab::Profiling::Utils::GetUtils(); 64 | 65 | 66 | return context; 67 | } 68 | 69 | 70 | PluginContext &GetPluginContext() 71 | { 72 | static PluginContext context; 73 | 74 | 75 | return context; 76 | } 77 | }}} 78 | -------------------------------------------------------------------------------- /Plugins/iOS/libKLab_Profiling.a.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 050a49c2278af274da0ed40bc4adc84d 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | platformData: 13 | - first: 14 | '': Any 15 | second: 16 | enabled: 0 17 | settings: 18 | Exclude Android: 1 19 | Exclude Editor: 1 20 | Exclude Linux: 1 21 | Exclude Linux64: 1 22 | Exclude LinuxUniversal: 1 23 | Exclude OSXUniversal: 1 24 | Exclude Win: 1 25 | Exclude Win64: 1 26 | Exclude iOS: 0 27 | - first: 28 | Android: Android 29 | second: 30 | enabled: 0 31 | settings: 32 | CPU: ARMv7 33 | - first: 34 | Any: 35 | second: 36 | enabled: 0 37 | settings: {} 38 | - first: 39 | Editor: Editor 40 | second: 41 | enabled: 0 42 | settings: 43 | CPU: AnyCPU 44 | DefaultValueInitialized: true 45 | OS: AnyOS 46 | - first: 47 | Facebook: Win 48 | second: 49 | enabled: 0 50 | settings: 51 | CPU: AnyCPU 52 | - first: 53 | Facebook: Win64 54 | second: 55 | enabled: 0 56 | settings: 57 | CPU: AnyCPU 58 | - first: 59 | Standalone: Linux 60 | second: 61 | enabled: 0 62 | settings: 63 | CPU: x86 64 | - first: 65 | Standalone: Linux64 66 | second: 67 | enabled: 0 68 | settings: 69 | CPU: x86_64 70 | - first: 71 | Standalone: OSXUniversal 72 | second: 73 | enabled: 0 74 | settings: 75 | CPU: AnyCPU 76 | - first: 77 | Standalone: Win 78 | second: 79 | enabled: 0 80 | settings: 81 | CPU: AnyCPU 82 | - first: 83 | Standalone: Win64 84 | second: 85 | enabled: 0 86 | settings: 87 | CPU: AnyCPU 88 | - first: 89 | iPhone: iOS 90 | second: 91 | enabled: 1 92 | settings: 93 | AddToEmbeddedBinaries: false 94 | CompileFlags: 95 | FrameworkDependencies: 96 | userData: 97 | assetBundleName: 98 | assetBundleVariant: 99 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/ATrace.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #if (KLAB_PROFILING_HAS_ATRACE) 14 | #include 15 | #endif 16 | 17 | 18 | // ------------------- // 19 | // ANDOID NATIVE TRACE // 20 | // ------------------- // 21 | 22 | namespace KLab { namespace Profiling { namespace Trace 23 | { 24 | ATrace::ATrace() : IsTracing(nullptr) 25 | { 26 | #if (KLAB_PROFILING_HAS_ATRACE) 27 | // Try load symbols 28 | _libAndroid = dlopen("libandroid.so", RTLD_NOW | RTLD_LOCAL); 29 | 30 | 31 | if (_libAndroid) 32 | { 33 | IsTracing = reinterpret_cast(dlsym(_libAndroid, "ATrace_isEnabled")); 34 | EnterSection = reinterpret_cast(dlsym(_libAndroid, "ATrace_beginSection")); 35 | LeaveSection = reinterpret_cast(dlsym(_libAndroid, "ATrace_endSection")); 36 | 37 | 38 | if (!IsTracing) 39 | { 40 | dlclose(_libAndroid); 41 | 42 | 43 | _libAndroid = nullptr; 44 | } 45 | } 46 | #endif 47 | } 48 | 49 | 50 | void ATrace::Unload() 51 | { 52 | #if (KLAB_PROFILING_HAS_ATRACE) 53 | if (IsTracing) 54 | { 55 | dlclose(_libAndroid); 56 | 57 | 58 | _libAndroid = nullptr; 59 | IsTracing = nullptr; 60 | } 61 | #endif 62 | } 63 | 64 | 65 | ATrace *TryGetATrace() 66 | { 67 | static ATrace interface; 68 | 69 | 70 | return (interface ? &interface : nullptr); 71 | } 72 | }}} 73 | 74 | 75 | // ----------- // 76 | // PLUGIN INFO // 77 | // ----------- // 78 | 79 | int32_t KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_PluginInfo_SupportsAndroidNativeTrace() 80 | { 81 | return (KLab::Profiling::Trace::TryGetATrace() != nullptr); 82 | } 83 | -------------------------------------------------------------------------------- /Plugins~/BuildScripts/BuildIOS.sh: -------------------------------------------------------------------------------- 1 | #!bin/bash 2 | 3 | # Builds libraries for iOS 4 | echo -- iOS plugin build 5 | 6 | 7 | # Initialize arguments 8 | BuildScriptsDirectory="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" 9 | PluginDirectory="$BuildScriptsDirectory/.." 10 | TempDirectory="$PluginDirectory/.temp" 11 | BuildDirectory="$PluginDirectory/../Plugins/iOS" 12 | UnityPluginApiDirectory="$UNITY_PLUGIN_API_ROOT" 13 | ToolchainFile="$PluginDirectory/Vendor/ios-cmake/ios.toolchain.cmake" 14 | 15 | BuildType="Release" 16 | 17 | 18 | # Parse command line options 19 | echo 20 | echo 21 | echo [User Options] 22 | 23 | 24 | for arg in "$0" 25 | do 26 | if [ "arg" = "--debug" ]; then 27 | BuildType="Debug" 28 | fi 29 | done 30 | 31 | 32 | if [ "$BuildType" = "Release" ]; then 33 | echo -- Build \'$BuildType\' \(pass \'--debug\' on command line for debug build\) 34 | else 35 | echo -- Build \'$BuildType\' 36 | fi 37 | 38 | 39 | # Try locate Unity API relatively 40 | if [ ! -d "$UnityPluginApiDirectory" ]; then 41 | UnityPluginApiDirectory="$PluginDirectory/Vendor/UnityPluginApi" 42 | fi 43 | 44 | 45 | # Validate 46 | echo 47 | echo 48 | echo [Validation] 49 | 50 | if [ -f "$ToolchainFile" ]; then 51 | echo -- CMake iOS toolchain found 52 | else 53 | echo -- \[ERROR\] CMake iOS toolchain not found 54 | echo " (CMake iOS toolchain (https://github.com/leetal/ios-cmake) expected in './Plugin~/Vendor/ios-cmake')" 55 | 56 | exit -1 57 | fi 58 | if [ -f "$UnityPluginApiDirectory/IUnityInterface.h" ]; then 59 | echo -- Unity Plugin API found 60 | else 61 | echo -- \[ERROR\] Unity Plugin API not found 62 | echo " ('UNITY_PLUGIN_API_ROOT' environment variable or header files in './Plugin~/Vendor/UnityPluginApi' expected)" 63 | 64 | exit -1 65 | fi 66 | 67 | 68 | # Clear temp 69 | if [ -d "$TempDirectory" ]; then 70 | rm -rf "$TempDirectory" 71 | fi 72 | 73 | 74 | # Build binary 75 | echo 76 | echo 77 | echo [Fat Build] 78 | 79 | mkdir $TempDirectory 80 | 81 | cd $TempDirectory 82 | cmake "$PluginDirectory" -G"Unix Makefiles" -DCMAKE_BUILD_TYPE="$BuildType" -DCMAKE_TOOLCHAIN_FILE=$ToolchainFile -DKLAB_PROFILING_UNITY_PLUGIN_API_PATH="$UnityPluginApiDirectory" -DKLAB_PROFILING_OUTPUT_DIRECTORY="$BuildDirectory" 83 | make 84 | cd .. 85 | 86 | rm -rf "$TempDirectory" 87 | -------------------------------------------------------------------------------- /Plugins/Linux/x64/libKLab_Profiling.so.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: 248c111114b92bf4998ea0fbbc486a32 3 | PluginImporter: 4 | externalObjects: {} 5 | serializedVersion: 2 6 | iconMap: {} 7 | executionOrder: {} 8 | defineConstraints: [] 9 | isPreloaded: 0 10 | isOverridable: 0 11 | isExplicitlyReferenced: 0 12 | platformData: 13 | - first: 14 | '': Any 15 | second: 16 | enabled: 0 17 | settings: 18 | Exclude Android: 1 19 | Exclude Editor: 0 20 | Exclude Linux: 1 21 | Exclude Linux64: 0 22 | Exclude LinuxUniversal: 0 23 | Exclude OSXUniversal: 1 24 | Exclude Win: 0 25 | Exclude Win64: 0 26 | Exclude iOS: 1 27 | - first: 28 | Android: Android 29 | second: 30 | enabled: 0 31 | settings: 32 | CPU: ARMv7 33 | - first: 34 | Any: 35 | second: 36 | enabled: 0 37 | settings: {} 38 | - first: 39 | Editor: Editor 40 | second: 41 | enabled: 1 42 | settings: 43 | CPU: x86_64 44 | DefaultValueInitialized: true 45 | OS: Linux 46 | - first: 47 | Facebook: Win 48 | second: 49 | enabled: 0 50 | settings: 51 | CPU: AnyCPU 52 | - first: 53 | Facebook: Win64 54 | second: 55 | enabled: 0 56 | settings: 57 | CPU: AnyCPU 58 | - first: 59 | Standalone: Linux 60 | second: 61 | enabled: 0 62 | settings: 63 | CPU: None 64 | - first: 65 | Standalone: Linux64 66 | second: 67 | enabled: 1 68 | settings: 69 | CPU: x86_64 70 | - first: 71 | Standalone: LinuxUniversal 72 | second: 73 | enabled: 1 74 | settings: 75 | CPU: x86_64 76 | - first: 77 | Standalone: OSXUniversal 78 | second: 79 | enabled: 0 80 | settings: 81 | CPU: None 82 | - first: 83 | Standalone: Win 84 | second: 85 | enabled: 1 86 | settings: 87 | CPU: AnyCPU 88 | - first: 89 | Standalone: Win64 90 | second: 91 | enabled: 1 92 | settings: 93 | CPU: AnyCPU 94 | - first: 95 | iPhone: iOS 96 | second: 97 | enabled: 0 98 | settings: 99 | AddToEmbeddedBinaries: false 100 | CompileFlags: 101 | FrameworkDependencies: 102 | userData: 103 | assetBundleName: 104 | assetBundleVariant: 105 | -------------------------------------------------------------------------------- /Tests/KLab/Profiling/Tests/LowLevel/TraceUtilityTests.cs: -------------------------------------------------------------------------------- 1 | using KLab.Profiling.LowLevel; 2 | using NUnit.Framework; 3 | using System; 4 | using System.Collections; 5 | using Unity.Collections; 6 | using Unity.Collections.LowLevel.Unsafe; 7 | using UnityEngine; 8 | using UnityEngine.TestTools; 9 | 10 | 11 | namespace KLab.Profiling.Tests.LowLevel 12 | { 13 | /// 14 | /// tests 15 | /// 16 | internal sealed class TraceUtilityTests 17 | { 18 | [UnityTest] 19 | public IEnumerator BeginTrace_EndTrace_Succeeds() 20 | { 21 | // Arrange 22 | var eventBuffer = AllocateEventBuffer(2048); 23 | var result = new Profiling.LowLevel.Trace.TraceInfo(); 24 | 25 | 26 | // Act 27 | { 28 | TraceUtility.BeginTrace(eventBuffer, 2048); 29 | 30 | 31 | // Trace some frames 32 | yield return new WaitForEndOfFrame(); 33 | yield return new WaitForEndOfFrame(); 34 | yield return new WaitForEndOfFrame(); 35 | 36 | 37 | TraceUtility.EndTrace(ref result); 38 | } 39 | 40 | 41 | // Assert 42 | { 43 | Assert.Greater(result.EventCount, 0, "Expected trace events"); 44 | } 45 | 46 | 47 | // Clean up 48 | FreeEventBuffer(eventBuffer); 49 | } 50 | 51 | #region Helpers 52 | 53 | /// 54 | /// Allocates event buffer 55 | /// 56 | /// Capacity 57 | private static IntPtr AllocateEventBuffer(int capacity = 2048) 58 | { 59 | unsafe 60 | { 61 | var sizeof_ = UnsafeUtility.SizeOf(); 62 | var alignof_ = UnsafeUtility.AlignOf(); 63 | 64 | return (IntPtr)UnsafeUtility.Malloc((sizeof_ * capacity), alignof_, Allocator.Persistent); 65 | } 66 | } 67 | 68 | /// 69 | /// Frees event buffer 70 | /// 71 | /// Event buffer 72 | private static void FreeEventBuffer(IntPtr eventBuffer) 73 | { 74 | unsafe 75 | { 76 | UnsafeUtility.Free((void*)eventBuffer, Allocator.Persistent); 77 | } 78 | } 79 | 80 | #endregion 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/Utils.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #if !(KLAB_PROFILING_HAS_EXTERN_UTILS) 14 | #if (_WIN32) 15 | #include 16 | #elif (KLAB_PROFILING_HAS_PTHREAD) 17 | #include 18 | #endif 19 | #endif 20 | 21 | 22 | // ----- // 23 | // UTILS // 24 | // ----- // 25 | 26 | namespace KLab { namespace Profiling { namespace Utils 27 | { 28 | uint64_t IExternUtils::GetThreadID() 29 | { 30 | #if (_WIN32) 31 | return (uint64_t)GetCurrentThreadId(); 32 | #elif (KLAB_PROFILING_HAS_PTHREAD) 33 | return (uint64_t)pthread_self(); 34 | #else 35 | return (uint64_t)0; 36 | #endif 37 | } 38 | 39 | 40 | Utf8Buffer IExternUtils::ConvertUtf16ToUtf8(const char16_t *utf16String, const uint32_t utf16Length) 41 | { 42 | Utf8Buffer utf8 = { { 0 } }; 43 | 44 | 45 | #if (_WIN32) 46 | // Use Windows API if available 47 | if (!WideCharToMultiByte(CP_UTF8, 0, reinterpret_cast(utf16String), int(utf16Length), utf8.CString, sizeof(utf8.CString), nullptr, nullptr)) 48 | { 49 | // Silently handle conversion error 50 | utf8.CString[0] = '\0'; 51 | } 52 | #else 53 | // Memcopy 54 | auto storage = reinterpret_cast(utf16String); 55 | auto end = storage + (utf16Length * 2 ) + 1; 56 | 57 | 58 | if ((end - storage) > sizeof(utf8.CString)) 59 | { 60 | end = ( storage + sizeof(utf8.CString)); 61 | } 62 | 63 | 64 | for (size_t c = size_t(0); storage < end; ++storage, ++c) 65 | { 66 | utf8.CString[c] = *storage; 67 | } 68 | #endif 69 | 70 | 71 | return utf8; 72 | } 73 | 74 | 75 | IUtils &GetUtils() 76 | { 77 | #if (KLAB_PROFILING_HAS_EXTERN_UTILS) 78 | static IUtils *utils = LoadExternUtils(); 79 | 80 | 81 | return &utils; 82 | #else 83 | static IUtils utils; 84 | 85 | 86 | return utils; 87 | #endif 88 | } 89 | }}} 90 | -------------------------------------------------------------------------------- /Plugins/MacOS/KLab_Profiling.bundle.meta: -------------------------------------------------------------------------------- 1 | fileFormatVersion: 2 2 | guid: ac877ef70e1948d4a9cc0b765187f71f 3 | folderAsset: yes 4 | PluginImporter: 5 | externalObjects: {} 6 | serializedVersion: 2 7 | iconMap: {} 8 | executionOrder: {} 9 | defineConstraints: [] 10 | isPreloaded: 0 11 | isOverridable: 0 12 | isExplicitlyReferenced: 0 13 | platformData: 14 | - first: 15 | '': Any 16 | second: 17 | enabled: 0 18 | settings: 19 | Exclude Android: 1 20 | Exclude Editor: 0 21 | Exclude Linux: 1 22 | Exclude Linux64: 1 23 | Exclude LinuxUniversal: 1 24 | Exclude OSXUniversal: 0 25 | Exclude Win: 1 26 | Exclude Win64: 1 27 | Exclude iOS: 1 28 | - first: 29 | '': OSXIntel 30 | second: 31 | enabled: 1 32 | settings: {} 33 | - first: 34 | '': OSXIntel64 35 | second: 36 | enabled: 1 37 | settings: {} 38 | - first: 39 | Android: Android 40 | second: 41 | enabled: 0 42 | settings: 43 | CPU: ARMv7 44 | - first: 45 | Any: 46 | second: 47 | enabled: 0 48 | settings: {} 49 | - first: 50 | Editor: Editor 51 | second: 52 | enabled: 1 53 | settings: 54 | CPU: AnyCPU 55 | DefaultValueInitialized: true 56 | OS: OSX 57 | - first: 58 | Facebook: Win 59 | second: 60 | enabled: 0 61 | settings: 62 | CPU: AnyCPU 63 | - first: 64 | Facebook: Win64 65 | second: 66 | enabled: 0 67 | settings: 68 | CPU: AnyCPU 69 | - first: 70 | Standalone: Linux 71 | second: 72 | enabled: 0 73 | settings: 74 | CPU: x86 75 | - first: 76 | Standalone: Linux64 77 | second: 78 | enabled: 0 79 | settings: 80 | CPU: x86_64 81 | - first: 82 | Standalone: OSXUniversal 83 | second: 84 | enabled: 1 85 | settings: 86 | CPU: AnyCPU 87 | - first: 88 | Standalone: Win 89 | second: 90 | enabled: 0 91 | settings: 92 | CPU: AnyCPU 93 | - first: 94 | Standalone: Win64 95 | second: 96 | enabled: 0 97 | settings: 98 | CPU: AnyCPU 99 | - first: 100 | iPhone: iOS 101 | second: 102 | enabled: 0 103 | settings: 104 | AddToEmbeddedBinaries: false 105 | CompileFlags: 106 | FrameworkDependencies: 107 | userData: 108 | assetBundleName: 109 | assetBundleVariant: 110 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/PluginInfo.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | using System.Runtime.InteropServices; 7 | 8 | 9 | namespace KLab.Profiling 10 | { 11 | /// 12 | /// Info on plugin 13 | /// 14 | public static class PluginInfo 15 | { 16 | /// 17 | /// C functions 18 | /// 19 | private static class C 20 | { 21 | [DllImport(DllName, EntryPoint = "KLab_Profiling_PluginInfo_SupportsAndroidNativeTrace")] 22 | public static extern int SupportsAndroidNativeTrace(); 23 | 24 | 25 | [DllImport(DllName, EntryPoint = "KLab_Profiling_PluginInfo_SupportsExternTrace")] 26 | public static extern int SupportsExternTrace(); 27 | } 28 | 29 | 30 | /// 31 | /// Plugin DLL name 32 | /// 33 | #if UNITY_IOS && !UNITY_EDITOR 34 | internal const string DllName = "__Internal"; 35 | #else 36 | internal const string DllName = "KLab_Profiling"; 37 | #endif 38 | 39 | 40 | /// 41 | /// Flag whether plugin is available 42 | /// 43 | public static bool IsPluginAvailable 44 | { 45 | get 46 | { 47 | // No driver, no plugin... 48 | return PluginDriver.IsInitialized; 49 | } 50 | } 51 | 52 | 53 | /// 54 | /// Flag whether native tracing on Android is supported 55 | /// 56 | public static bool SupportsAndroidNativeTrace 57 | { 58 | get 59 | { 60 | if (!IsPluginAvailable) 61 | { 62 | return false; 63 | } 64 | 65 | 66 | return (C.SupportsAndroidNativeTrace() != 0); 67 | } 68 | } 69 | 70 | 71 | /// 72 | /// Flag whether extern tracing is supported 73 | /// 74 | public static bool SupportsExternTrace 75 | { 76 | get 77 | { 78 | if (!IsPluginAvailable) 79 | { 80 | return false; 81 | } 82 | 83 | 84 | return (C.SupportsExternTrace() != 0); 85 | } 86 | } 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /Plugins~/BuildScripts/BuildWindows.bat: -------------------------------------------------------------------------------- 1 | :: Builds libraries for Windows 2 | @echo off 3 | echo -- Windows plugin build 4 | 5 | 6 | :: Initialize arguments 7 | set PluginDirectory=%~dp0.. 8 | set TempDirectory=%PluginDirectory%\.temp 9 | set BuildDirectory=%PluginDirectory%\..\Plugins\Windows 10 | 11 | set UnityPluginApiDirectory=%UNITY_PLUGIN_API_ROOT% 12 | 13 | if "%VSWHERE%"=="" ( 14 | set "VSWHERE=%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" 15 | ) 16 | for /f "usebackq tokens=*" %%i in (`"%VSWHERE%" -latest -products * -requires Microsoft.Component.MSBuild -property installationPath`) do ( 17 | set VsDirectory=%%i 18 | ) 19 | set VsDevCmd="%VsDirectory%\Common7\Tools\VsDevCmd.bat" 20 | 21 | set BuildType="Release" 22 | 23 | 24 | :: Parse command line options 25 | echo. 26 | echo. 27 | echo [User Options] 28 | 29 | for /f "tokens=1*" %%a in ('echo %*') do ( 30 | if "%%a" == "--debug" ( 31 | set BuildType="Debug" 32 | ) 33 | ) 34 | 35 | if %BuildType%=="Release" ( 36 | echo -- Build %BuildType% ^(pass '--debug' on command line for debug build^) 37 | ) else ( 38 | echo -- Build %BuildType% 39 | ) 40 | 41 | 42 | :: Try locate Unity Plugin API relatively 43 | if not exist "%UnityPluginApiDirectory%" ( 44 | set UnityPluginApiDirectory=%PluginDirectory%\Vendor\UnityPluginAPI 45 | ) 46 | 47 | 48 | :: Validate 49 | echo. 50 | echo. 51 | echo [Validation] 52 | if exist "%VsDirectory%" ( 53 | echo -- Visual Studio found 54 | ) else ( 55 | echo -- [ERROR] Visual Studio not found 56 | echo ^(Make sure to have Visual Studio 2017 installed^) 57 | 58 | exit /b -1 59 | ) 60 | if exist "%UnityPluginApiDirectory%\IUnityInterface.h" ( 61 | echo -- Unity Plugin API found 62 | ) else ( 63 | echo -- [ERROR] Unity Plugin API not found 64 | echo ^(Either 'UNITY_PLUGIN_API_ROOT' environment variable or headers in './Plugin~/Vendor/UnityPluginApi' expected^) 65 | 66 | exit /b -1 67 | ) 68 | 69 | 70 | :: Clear temp 71 | if exist "%TempDirectory%" ( 72 | rmdir /s /q "%TempDirectory%" 73 | ) 74 | 75 | 76 | :: Build x64 binary 77 | echo. 78 | echo. 79 | echo [x64 Build] 80 | 81 | mkdir "%TempDirectory%" 82 | 83 | cd "%TempDirectory%" 84 | call %VsDevCmd% -arch=x64 85 | cmake %PluginDirectory% -G"NMake Makefiles" -DCMAKE_BUILD_TYPE=%BuildType% -DKLAB_PROFILING_UNITY_PLUGIN_API_PATH="%UnityPluginApiDirectory%" -DKLAB_PROFILING_OUTPUT_DIRECTORY="%BuildDirectory%\x64" 86 | nmake 87 | cd .. 88 | 89 | rmdir /s /q "%TempDirectory%" 90 | 91 | 92 | 93 | :: Exit 94 | echo. 95 | echo. 96 | 97 | if %ERRORLEVEL%==0 ( 98 | echo -- Exiting with success 99 | ) else ( 100 | echo -- Exiting with error %ERRORLEVEL% 101 | ) 102 | 103 | exit /b %ERRORLEVEL% 104 | -------------------------------------------------------------------------------- /Plugins~/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10) 2 | 3 | 4 | # Detect macOS/iOS 5 | if (IOS_PLATFORM) 6 | set(IOS TRUE) 7 | elseif (APPLE) 8 | set(MACOS TRUE) 9 | endif () 10 | 11 | 12 | # Expose options 13 | set(KLAB_PROFILING_UNITY_PLUGIN_API_PATH "" CACHE PATH "[Required] Path to folder containing Unity native plugin headers") 14 | set(KLAB_PROFILING_EXTERN_TRACE_TARGET "" CACHE STRING "[Optional] Name of extern trace library CMake target") 15 | set(KLAB_PROFILING_EXTERN_UTILS_TARGET "" CACHE STRING "[Optional] Name of extern utility library CMake target") 16 | 17 | 18 | # Validate options 19 | if (EXISTS "${KLAB_PROFILING_UNITY_PLUGIN_API_PATH}/IUnityInterface.h") 20 | if (NOT EXISTS "${KLAB_PROFILING_UNITY_PLUGIN_API_PATH}/IUnityProfilerCallbacks.h") 21 | message(FATAL_ERROR "Unity 2018.2+ required") 22 | endif () 23 | else () 24 | message(FATAL_ERROR "Path to Unity Plugin API folder required") 25 | endif () 26 | 27 | 28 | # Assemble source files and settings 29 | set(privateDefines "") 30 | set(privateIncludes ${KLAB_PROFILING_UNITY_PLUGIN_API_PATH} Internal) 31 | set(privateLinkLibraries "") 32 | set(sourceFiles 33 | SourceFiles/ATrace.cpp 34 | SourceFiles/CSharpTrace.cpp 35 | SourceFiles/ExternTrace.cpp 36 | SourceFiles/Plugin.cpp 37 | SourceFiles/PluginContext.cpp 38 | SourceFiles/Utils.cpp) 39 | 40 | 41 | if (TARGET ${KLAB_PROFILING_EXTERN_TRACE_TARGET}) 42 | message(STATUS "Extern utils found") 43 | list(APPEND privateDefines KLAB_PROFILING_HAS_EXTERN_UTILS=1) 44 | list(APPEND privateLinkLibraries ${KLAB_PROFILING_EXTERN_TRACE_TARGET}) 45 | endif () 46 | 47 | if (TARGET ${KLAB_PROFILING_EXTERN_UTILS_TARGET}) 48 | message(STATUS "Extern trace found") 49 | list(APPEND privateDefines KLAB_PROFILING_HAS_EXTERN_TRACE=1) 50 | list(APPEND privateLinkLibraries ${KLAB_PROFILING_EXTERN_UTILS_TARGET}) 51 | endif () 52 | 53 | if (ANDROID) 54 | message(STATUS "Android trace found") 55 | list(APPEND privateDefines KLAB_PROFILING_HAS_ATRACE=1) 56 | endif () 57 | 58 | find_package(Threads) 59 | if (CMAKE_USE_PTHREADS_INIT) 60 | message(STATUS "pthread found") 61 | list(APPEND privateDefines KLAB_PROFILING_HAS_PTHREAD=1) 62 | list(APPEND privateLinkLibraries Threads::Threads) 63 | endif() 64 | 65 | 66 | # Create library 67 | set(libraryType SHARED) 68 | if (IOS) 69 | set(libraryType STATIC) 70 | elseif (MACOS) 71 | set(libraryType MODULE) 72 | endif () 73 | 74 | add_library(KLab_Profiling ${libraryType} ${sourceFiles}) 75 | target_compile_definitions(KLab_Profiling PRIVATE ${privateDefines}) 76 | target_link_libraries(KLab_Profiling PRIVATE ${privateLinkLibraries}) 77 | target_include_directories(KLab_Profiling PUBLIC Include PRIVATE ${privateIncludes}) 78 | 79 | if (KLAB_PROFILING_OUTPUT_DIRECTORY) 80 | set_target_properties(KLab_Profiling 81 | PROPERTIES 82 | ARCHIVE_OUTPUT_DIRECTORY "${KLAB_PROFILING_OUTPUT_DIRECTORY}" 83 | LIBRARY_OUTPUT_DIRECTORY "${KLAB_PROFILING_OUTPUT_DIRECTORY}" 84 | RUNTIME_OUTPUT_DIRECTORY "${KLAB_PROFILING_OUTPUT_DIRECTORY}") 85 | endif () 86 | 87 | if (IOS OR MACOS) 88 | set_target_properties(KLab_Profiling PROPERTIES CXX_STANDARD 11) 89 | endif () 90 | 91 | if (MACOS) 92 | set_target_properties(KLab_Profiling PROPERTIES BUNDLE TRUE) 93 | endif () 94 | -------------------------------------------------------------------------------- /Plugins~/BuildScripts/BuildAndroid.bat: -------------------------------------------------------------------------------- 1 | :: Builds libraries for Android 2 | @echo off 3 | echo -- Android plugin build 4 | 5 | 6 | :: Initialize arguments 7 | set PluginDirectory=%~dp0.. 8 | set TempDirectory=%PluginDirectory%\.temp 9 | set BuildDirectory=%PluginDirectory%\..\Plugins\Android 10 | 11 | set UnityPluginApiDirectory=%UNITY_PLUGIN_API_ROOT% 12 | 13 | set AndroidNdkRoot=%ANDROID_NDK_ROOT% 14 | set MakeProgram=%AndroidNdkRoot%\prebuilt\windows-x86_64\bin\make.exe 15 | set ToolchainFile=%AndroidNdkRoot%\build\cmake\android.toolchain.cmake 16 | 17 | set BuildType="Release" 18 | 19 | 20 | :: Parse command line options 21 | echo. 22 | echo. 23 | echo [User Options] 24 | 25 | for /f "tokens=1*" %%a in ('echo %*') do ( 26 | if "%%a" == "--debug" ( 27 | set BuildType="Debug" 28 | ) 29 | ) 30 | 31 | if %BuildType% == "Release" ( 32 | echo -- Build %BuildType% ^(pass '--debug' on command line for debug build^) 33 | ) else ( 34 | echo -- Build %BuildType% 35 | ) 36 | 37 | 38 | :: Try locate Unity Plugin API relatively 39 | if not exist "%UnityPluginApiDirectory%" ( 40 | set UnityPluginApiDirectory=%PluginDirectory%\Vendor\UnityPluginAPI 41 | ) 42 | 43 | 44 | :: Validate environment 45 | echo. 46 | echo. 47 | echo [Validation] 48 | if exist "%AndroidNdkRoot%" ( 49 | echo -- Android NDK found 50 | ) else ( 51 | echo -- [ERROR] Android NDK not found 52 | echo ^('ANDROID_NDK_ROOT' environment variable expected^) 53 | 54 | exit /b -1 55 | ) 56 | if exist "%MakeProgram%" ( 57 | echo -- Android NDK make found 58 | ) else ( 59 | echo -- [ERROR] Android NDK make found 60 | echo ^(64-bit environment expected^) 61 | 62 | exit /b -1 63 | ) 64 | if exist "%UnityPluginApiDirectory%\IUnityInterface.h" ( 65 | echo -- Unity Plugin API found 66 | ) else ( 67 | echo -- [ERROR] Unity Plugin API not found 68 | echo ^(Either 'UNITY_PLUGIN_API_ROOT' environment variable or headers in './Plugin~/Vendor/UnityPluginApi' expected^) 69 | 70 | exit -1 71 | ) 72 | 73 | 74 | :: Clear temp 75 | if exist "%TempDirectory%" ( 76 | rmdir /s /q "%TempDirectory%" 77 | ) 78 | 79 | 80 | :: Build arm64-v8a binary 81 | set Abi="arm64-v8a" 82 | set OutputDirectory=%BuildDirectory%\arm64-v8a 83 | 84 | call :ExecuteBuild 85 | 86 | 87 | :: Build armeabi-v7a binary 88 | set Abi="armeabi-v7a" 89 | set OutputDirectory=%BuildDirectory%\armeabi-v7a 90 | 91 | call :ExecuteBuild 92 | 93 | 94 | :: Build x86 binary 95 | set Abi="x86" 96 | set OutputDirectory=%BuildDirectory%\x86 97 | 98 | call :ExecuteBuild 99 | 100 | 101 | :: Exit 102 | echo. 103 | echo. 104 | 105 | if %ERRORLEVEL%==0 ( 106 | echo -- Exiting with success 107 | ) else ( 108 | echo -- Exiting with error %ERRORLEVEL% 109 | ) 110 | 111 | exit /b %ERRORLEVEL% 112 | 113 | 114 | :: Executes builds 115 | :ExecuteBuild 116 | echo. 117 | echo. 118 | echo [%Abi:~1,-1% Build] 119 | 120 | mkdir "%TempDirectory%" 121 | 122 | cd "%TempDirectory%" 123 | cmake %PluginDirectory% -G"Unix Makefiles" -DCMAKE_BUILD_TYPE=%BuildType% -DCMAKE_MAKE_PROGRAM=%MakeProgram% -DCMAKE_TOOLCHAIN_FILE=%ToolchainFile% -DANDROID_ABI=%Abi% -DKLAB_PROFILING_UNITY_PLUGIN_API_PATH="%UnityPluginApiDirectory%" -DKLAB_PROFILING_OUTPUT_DIRECTORY="%OutputDirectory%" 124 | call %MakeProgram% 125 | cd .. 126 | 127 | rmdir /s /q "%TempDirectory%" 128 | -------------------------------------------------------------------------------- /Plugins~/Include/KLab/Profiling.hpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #pragma once 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #include 14 | 15 | 16 | // ----- // 17 | // TRACE // 18 | // ----- // 19 | 20 | namespace KLab { namespace Profiling { namespace Trace 21 | { 22 | /// Info on trace section 23 | struct SectionInfo final 24 | { 25 | /// Group name as null-terminated UTF-8 string 26 | const char *GroupName; 27 | /// Section name as null-terminated UTF-8 string 28 | const char *Name; 29 | /// C-casted thread ID 30 | uint64_t ThreadID; 31 | /// Section color as 32-bit RGBA 32 | uint32_t Color; 33 | // [Unused] Padding 34 | uint32_t _padding; 35 | }; 36 | 37 | 38 | // Trace interface 39 | struct IExternTrace 40 | { 41 | /// Flags whether should trace 42 | /// @return whether tracer is tracing 43 | virtual bool IsTracing() = 0; 44 | /// Handles entering section enter 45 | /// @param section - Info on section 46 | virtual void EnterSection(const SectionInfo §ion) = 0; 47 | // Handles section leave 48 | /// @param section - Info on section 49 | virtual void LeaveSection(const SectionInfo §ion) = 0; 50 | /// [Optional] Unloads interface 51 | virtual void Unload() {} 52 | 53 | // Allows virtual destruction 54 | virtual ~IExternTrace() {} 55 | }; 56 | 57 | 58 | /// Loads extern trace interface 59 | /// @return the interface 60 | #if KLAB_PROFILING_HAS_EXTERN_TRACE 61 | extern IExternTrace &LoadExternTrace(); 62 | #endif 63 | }}} 64 | 65 | 66 | // ----- // 67 | // UTILS // 68 | // ----- // 69 | 70 | namespace KLab { namespace Profiling { namespace Utils 71 | { 72 | /// Null-terminated UTF-8 string buffer 73 | struct Utf8Buffer final 74 | { 75 | /// C-string storage 76 | char CString[128]; 77 | }; 78 | 79 | 80 | /// Utility functions interface 81 | struct IUtils 82 | { 83 | /// [Optional] Gets C-cast thread ID of current thread 84 | /// @return the thread ID 85 | virtual uint64_t GetThreadID(); 86 | /// [Optional] Converts UTF-16 string to UTF-8 string 87 | /// @param utf16String - String to convert 88 | /// @param utf16Length - Length of string (in characters) 89 | /// @return the string converted to UTF-8 90 | virtual Utf8Buffer ConvertUtf16ToUtf8(const char16_t *utf16String, const uint32_t utf16Length); 91 | /// [Optional] Unloads interface 92 | virtual void Unload() {} 93 | 94 | // Allows virtual destruction 95 | virtual ~IUtils() {} 96 | }; 97 | 98 | 99 | /// Extern Utility functions interface 100 | typedef IUtils IExternUtils; 101 | 102 | 103 | /// Loads extern utility interface 104 | /// @return the interface 105 | #if KLAB_PROFILING_HAS_EXTERN_UTILS 106 | extern IExternUtils &LoadExternUtils(IUtils &interface); 107 | #endif 108 | }}} 109 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/PluginDriver.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | using UnityEngine; 7 | using System.Collections; 8 | using System.Runtime.InteropServices; 9 | 10 | 11 | namespace KLab.Profiling 12 | { 13 | /// 14 | /// Plugin initializer 15 | /// 16 | internal sealed class PluginDriver : MonoBehaviour 17 | { 18 | /// 19 | /// C functions 20 | /// 21 | private static class C 22 | { 23 | [DllImport(PluginInfo.DllName, EntryPoint = "KLab_Profiling_Plugin_Initialize")] 24 | public static extern LowLevel.ErrorCode Initialize(); 25 | 26 | 27 | [DllImport(PluginInfo.DllName, EntryPoint = "KLab_Profiling_Plugin_Update")] 28 | public static extern void Update(); 29 | } 30 | 31 | 32 | /// 33 | /// Driver singleton instance 34 | /// 35 | public static PluginDriver Singleton { get; private set; } 36 | 37 | /// 38 | /// Flag whether driver is initialized 39 | /// 40 | internal static bool IsInitialized 41 | { 42 | get 43 | { 44 | return Singleton != null; 45 | } 46 | } 47 | 48 | 49 | /// 50 | /// Initializes plugin 51 | /// 52 | [RuntimeInitializeOnLoadMethod] 53 | private static void Initialize () 54 | { 55 | // INV How to handle platform support detection more gracefully 56 | var isPlatformSupported = Application.isEditor; 57 | isPlatformSupported = isPlatformSupported 58 | || (Application.platform == RuntimePlatform.Android) 59 | || (Application.platform == RuntimePlatform.IPhonePlayer) 60 | || (Application.platform == RuntimePlatform.LinuxPlayer) 61 | || (Application.platform == RuntimePlatform.OSXPlayer); 62 | 63 | 64 | if (!isPlatformSupported) 65 | { 66 | return; 67 | } 68 | 69 | 70 | // Initialize plugin 71 | var cInitializeResult = C.Initialize(); 72 | 73 | 74 | if (cInitializeResult != LowLevel.ErrorCode.NoError) 75 | { 76 | return; 77 | } 78 | 79 | 80 | // Create singleton 81 | { 82 | Debug.Assert(Singleton == null, "Expected singleton not to be created"); 83 | 84 | 85 | var owner = new GameObject(typeof(PluginDriver).FullName); 86 | Singleton = owner.AddComponent(); 87 | 88 | 89 | DontDestroyOnLoad(owner); 90 | } 91 | } 92 | 93 | 94 | /// 95 | /// Flips frame 96 | /// 97 | /// Scheduling timer 98 | private IEnumerator CUpdate() 99 | { 100 | for (;;) 101 | { 102 | yield return new WaitForEndOfFrame(); 103 | 104 | 105 | C.Update(); 106 | } 107 | } 108 | 109 | #region Unity Event Handling 110 | 111 | /// 112 | /// Schedules 113 | /// 114 | private void Awake() 115 | { 116 | StartCoroutine(CUpdate()); 117 | } 118 | 119 | #endregion 120 | } 121 | } 122 | -------------------------------------------------------------------------------- /Plugins~/Include/KLab/Profiling/CSharpInterface.h: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #pragma once 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #include 14 | 15 | 16 | #if (__cplusplus) 17 | extern "C" 18 | { 19 | #endif 20 | 21 | 22 | #if (_WIN32) 23 | #define KLAB_PROFILING_CSHARP_INTERFACE __declspec(dllexport) __stdcall 24 | #else 25 | #define KLAB_PROFILING_CSHARP_INTERFACE __attribute__ ((visibility("default"))) 26 | #endif 27 | 28 | 29 | // ----------- // 30 | // ERROR CODES // 31 | // ----------- // 32 | 33 | /// Error codes 34 | enum 35 | { 36 | /// Operation was successful 37 | KLab_Profiling_ErrorCode_NoError = 0, 38 | /// Requested feature not available 39 | KLab_Profiling_ErrorCode_NotAvailable = -1, 40 | /// Invalid arguments passed 41 | KLab_Profiling_ErrorCode_InvalidArgument = -2, 42 | /// Invalid state 43 | KLab_Profiling_ErrorCode_InvalidState = -3 44 | }; 45 | typedef int32_t KLab_Profiling_ErrorCode; 46 | 47 | 48 | // ------ // 49 | // PLUGIN // 50 | // ------ // 51 | 52 | /// Initializes plugin 53 | /// @return ::KLab_Profiling_ErrorCode_NoError on success; an error code otherwise 54 | KLab_Profiling_ErrorCode KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_Plugin_Initialize(); 55 | /// Called once per game frame to allow internal update 56 | void KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_Plugin_Update(); 57 | 58 | 59 | // ----------- // 60 | // PLUGIN INFO // 61 | // ----------- // 62 | 63 | /// Gets whether native Android tracing API is available 64 | /// @return 1 if available; 0 otherwise 65 | int32_t KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_PluginInfo_SupportsAndroidNativeTrace(); 66 | /// Gets whether extern tracer is available 67 | /// @return 1 if available; 0 otherwise 68 | int32_t KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_PluginInfo_SupportsExternTrace(); 69 | 70 | 71 | // ----- // 72 | // TRACE // 73 | // ----- // 74 | 75 | /// Trace event type 76 | enum 77 | { 78 | /// Section enter event 79 | KLab_Profiling_Trace_EventType_EnterSection = 0, 80 | /// Section leave event 81 | KLab_Profiling_Trace_EventType_LeaveSection = 1 82 | }; 83 | typedef uint32_t KLab_Profiling_Trace_EventType; 84 | 85 | 86 | /// Trace event info 87 | typedef struct 88 | { 89 | /// Name of section 90 | char Name[32]; 91 | /// Name of group 92 | char GroupName[16]; 93 | /// Offset since trace frame flip in nanoseconds 94 | uint64_t TimestampNs; 95 | /// C-casted thread ID 96 | uint64_t ThreadID; 97 | /// Event type 98 | uint32_t Type; 99 | /// RGBA Color 100 | uint32_t Color; 101 | } 102 | KLab_Profiling_Trace_EventInfo; 103 | 104 | 105 | /// Trace info 106 | typedef struct 107 | { 108 | /// Duration of tracee in nanoseconds 109 | uint64_t DurationNs; 110 | /// Number of trace events 111 | uint32_t EventCount; 112 | /// Flag whether buffer couldn't fit trace events 113 | uint32_t DidRunOutOfEventMemory; 114 | } 115 | KLab_Profiling_Trace_TraceInfo; 116 | 117 | 118 | /// Enables C# callback driven tracing 119 | /// @param eventBuffer - Buffer for trace events 120 | /// @param eventBufferSize - Capacity of buffer 121 | /// @return ::KLab_Profiling_ErrorCode_NoError on success; an error code otherwise 122 | KLab_Profiling_ErrorCode KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_TraceUtility_BeginTrace(KLab_Profiling_Trace_EventInfo *eventBuffer, const int32_t eventBufferSize); 123 | /// Ends C# started tracing 124 | /// @param info - Buffer for info on trace 125 | /// @return ::KLab_Profiling_ErrorCode_NoError on success; an error code otherwise 126 | KLab_Profiling_ErrorCode KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_TraceUtility_EndTrace(KLab_Profiling_Trace_TraceInfo *info); 127 | 128 | 129 | #if (__cplusplus) 130 | } 131 | #endif 132 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # *KLab Profiling for Unity* 2 | 3 | *KLab Profiling for Unity* helps you profile your *Unity* projects. 4 | 5 | 6 | ## Tracing 7 | 8 | Building on the [native profiler plugin API introduced with Unity 2018.2](https://unity3d.com/jp/unity/whats-new/unity-2018.2.0), this library 9 | 1. allows you to get detailed info on Unity profiler trace events through *C#* callbacks, 10 | 1. automatically forwards trace events to [Android's tracing API](https://developer.android.com/ndk/guides/tracing) if available, and 11 | 1. allows you to handle trace events in *C++*. 12 | 13 | If you're interested in how to handle trace events in *C#*, see [here](Runtime/KLab/Profiling/LowLevel/TraceUtility.cs) for the interface, 14 | and [here](Tests/KLab/Profiling/Tests/LowLevel/TraceUtilityTests#L16) for an example. 15 | At *KLab* we use the *C#* interface for uploading the trace data to cloud storage for later analysis in long run performance tests. 16 | 17 | If you want to handle trace events in *C++* you have to implement the trace interface and 18 | link your implementation to the library during native build. 19 | See [here](Plugins~/Include/Klab/Profiling.hpp#L39) for the interface you have to implement. 20 | The *CMake* project provides a [convenience option for linking your trace handler](Plugins~/CMakeLists.txt#L14). 21 | 22 | The library uses a [utility interface](Plugins~/Include/Klab/Profiling.hpp#L83) 23 | for querying the ID of the execution thread and for converting UTF-16 strings to UTF-8. 24 | The interface works out-of-the-box on *Win32* and *POSIX* platforms. 25 | You can replace the default interface by providing a custom implementation and linking to it during native build. 26 | Again, the *CMake* project provides a [convenience option for that](Plugins~/CMakeLists.txt#L15). 27 | 28 | 29 | ## Importing Into Unity 30 | 31 | The library includes prebuilt plugins for *Android*, *iOS*, *Linux*, *macOS*, and *Win32* and can be imported easily as a Unity package. 32 | It doesn't have any dependencies on other packages, but currently requires *Unity* 2018.2+. 33 | 34 | 35 | ## Native Plugin Build 36 | 37 | [Build scripts](Plugins~/BuildScripts) are available for building native *Android*, *iOS*, *Linux*, *macOS*, and *Win32* libraries. 38 | 39 | ### Common Prerequisites 40 | 41 | 1. *Makefiles* are generated with [*CMake*](https://cmake.org/). Make sure to have *CMake* 3.10+ installed and added to your path. 42 | 1. *Unity* plugin API header files have to be provided. The headers come with the *Unity Editor*. Either set `UNITY_PLUGIN_API_PATH` to point at the folder including the header files or opy them into './Plugin~/Vendor/UnityPluginApi/'. 43 | 44 | ### *Android* Prerequisites 45 | 46 | 1. Make sure to have the [*Android NDK*](https://developer.android.com/ndk/) available and `ANDROID_NDK_ROOT` as an environment variable pointing at its root folder. 47 | 48 | ### *iOS* Prerequisites 49 | 50 | 1. Make sure to have [*XCode*](https://developer.apple.com/xcode/) installed and available on the command line. 51 | 1. Clone (or download) [*ios-cmake*](https://github.com/leetal/ios-cmake) into `./Plugin~/Vendor/ios-cmake/` 52 | 53 | ### *Linux* Prerequisites 54 | 55 | 1. Make sure to have build essentials available on the command line. 56 | 57 | ### *macOS* Prerequisites 58 | 59 | 1. Make sure to have [*XCode*](https://developer.apple.com/xcode/) installed and available on the command line. 60 | 61 | ### *Win32* Prerequisites 62 | 63 | 1. Make sure to have [Visual Studio](https://visualstudio.microsoft.com) (2017+) and components for building *C++* installed. 64 | 65 | 66 | ## Contributing 67 | 68 | Fixing issues and contributing directly to the code base is more than welcome. A *rebase workflow* is preferred over branching out. 69 | Please stick to the [*Microsoft* naming guidelines](https://docs.microsoft.com/en-ca/dotnet/standard/design-guidelines/naming-guidelines) 70 | when contributing *C#* code and document public interfaces with *XML*. Please also stick to the guidelines for *C++*. 71 | For *C*, "emulate" namespaces by using underscores instead of the double colons in *C++*, i.e. write `KLab::Profiling` as `KLab_Profiling`. 72 | Public *C/C++* interfaces should be documented in [*Doxygen*](http://www.doxygen.org/) syntax if possible. 73 | 74 | 75 | ## Feedback 76 | 77 | - Request a new feature on GitHub 78 | - File a bug in GitHub Issues 79 | 80 | 81 | ## License 82 | 83 | Copyright (c) KLab Inc.. All rights reserved. 84 | 85 | Licensed under the [MIT](LICENSE) License. 86 | -------------------------------------------------------------------------------- /Runtime/KLab/Profiling/LowLevel/TraceUtility.cs: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | using System; 7 | using System.Runtime.InteropServices; 8 | 9 | 10 | namespace KLab.Profiling.LowLevel 11 | { 12 | namespace Trace 13 | { 14 | /// 15 | /// Trace event type 16 | /// 17 | public enum EventType : int 18 | { 19 | /// 20 | /// Enter section event 21 | /// 22 | EnterSection = 0, 23 | 24 | /// 25 | /// Leave section event 26 | /// 27 | LeaveSection = 1 28 | } 29 | 30 | 31 | /// 32 | /// Trace event info 33 | /// 34 | [StructLayout(LayoutKind.Sequential)] 35 | public unsafe struct EventInfo 36 | { 37 | /// 38 | /// Thread name as null-terminated UTF-8 string 39 | /// 40 | public fixed byte Name[32]; 41 | 42 | /// 43 | /// Thread name as null-terminated UTF-8 string 44 | /// 45 | public fixed byte GroupName[16]; 46 | 47 | /// 48 | /// Offset since frame flip in nanoseconds 49 | /// 50 | public ulong TimestampNs; 51 | 52 | /// 53 | /// Thread name as null-terminated UTF-8 string 54 | /// 55 | public ulong ThreadID; 56 | 57 | /// 58 | /// Thread name as null-terminated UTF-8 string 59 | /// 60 | public EventType Type; 61 | 62 | /// 63 | /// RGBA marker color 64 | /// 65 | public uint Color; 66 | } 67 | 68 | 69 | /// 70 | /// Info on trace frame flip 71 | /// 72 | [StructLayout(LayoutKind.Sequential)] 73 | public struct TraceInfo 74 | { 75 | /// 76 | /// Duration of traced frame in nanoseconds 77 | /// 78 | public ulong DurationNs; 79 | 80 | /// 81 | /// Number of trace events 82 | /// 83 | public uint EventCount; 84 | 85 | /// 86 | /// Flag whether event buffer ran out of memory 87 | /// 88 | public uint DidRunOutOfEventMemory; 89 | } 90 | } 91 | 92 | 93 | /// 94 | /// Utilities for C# callback-driven tracing 95 | /// 96 | public static class TraceUtility 97 | { 98 | /// 99 | /// C functions 100 | /// 101 | private static class C 102 | { 103 | [DllImport(PluginInfo.DllName, EntryPoint = "KLab_Profiling_TraceUtility_BeginTrace")] 104 | public static extern ErrorCode BeginTrace(IntPtr eventBufferFrame, int eventBufferCapacity); 105 | 106 | 107 | [DllImport(PluginInfo.DllName, EntryPoint = "KLab_Profiling_TraceUtility_EndTrace")] 108 | public static extern ErrorCode EndTrace(ref Trace.TraceInfo info); 109 | } 110 | 111 | 112 | /// 113 | /// Begins tracing 114 | /// 115 | /// array buffer 116 | /// Capacity of buffer for 117 | /// on success; an error otherwise 118 | public static ErrorCode BeginTrace(IntPtr eventBuffer, int eventBufferCapacity) 119 | { 120 | // Validate availability 121 | if (!PluginInfo.IsPluginAvailable) 122 | { 123 | return ErrorCode.NotAvailable; 124 | } 125 | 126 | 127 | // Validate arguments 128 | if ((eventBuffer == IntPtr.Zero) || (eventBufferCapacity <= 0)) 129 | { 130 | return ErrorCode.InvalidArgument; 131 | } 132 | 133 | 134 | return C.BeginTrace(eventBuffer, eventBufferCapacity); 135 | } 136 | 137 | 138 | /// 139 | /// Ends tracing 140 | /// 141 | public static ErrorCode EndTrace(ref Trace.TraceInfo info) 142 | { 143 | // Validate availability 144 | if (!PluginInfo.IsPluginAvailable) 145 | { 146 | return ErrorCode.NotAvailable; 147 | } 148 | 149 | 150 | return C.EndTrace(ref info); 151 | } 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/CSharpTrace.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // ------- // 10 | // HELPERS // 11 | // ------- // 12 | 13 | namespace KLab { namespace Profiling { namespace Trace 14 | { 15 | // Copies string 16 | // @param out - Output buffer 17 | // @param in - Input string 18 | // @param outCapacity - Capacity of output buffer in characters 19 | static void _copyString(char *out, const char *in, const size_t outCapacity) 20 | { 21 | // Null-terminate out 22 | out[outCapacity - 1] = '\0'; 23 | 24 | 25 | for (auto end = (out + outCapacity); out < end; ++out, ++in) 26 | { 27 | *out = *in; 28 | 29 | 30 | if (!(*in)) 31 | { 32 | break; 33 | } 34 | } 35 | } 36 | 37 | 38 | // Initializes event KLab_Profiling_Trace_EventInfo 39 | // @param event - Info to initialize 40 | // @param type - Trace event type 41 | // @param info - Trace section info 42 | // @param timestampNs - Trace event timestamp in nanoseconds 43 | static void _initializeEvent(KLab_Profiling_Trace_EventInfo &event, const KLab_Profiling_Trace_EventType type, const SectionInfo §ion, const uint64_t timestampNs) 44 | { 45 | // Store scalars 46 | event.Type = type; 47 | event.TimestampNs = timestampNs; 48 | event.ThreadID = section.ThreadID; 49 | event.Color = section.Color; 50 | 51 | 52 | // Copy strings 53 | _copyString(event.GroupName, section.GroupName, sizeof(event.GroupName)); 54 | _copyString(event.Name, section.Name, sizeof(event.Name)); 55 | } 56 | }}} 57 | 58 | 59 | // -------- // 60 | // C# TRACE // 61 | // -------- // 62 | 63 | namespace KLab { namespace Profiling { namespace Trace 64 | { 65 | bool CSharpTrace::IsTracing() const 66 | { 67 | return _isTracing; 68 | } 69 | 70 | 71 | void CSharpTrace::EnterSection(const SectionInfo §ion) 72 | { 73 | auto event = _eventBuffer.Allocate(); 74 | 75 | 76 | if (event) 77 | { 78 | _initializeEvent(*event, KLab_Profiling_Trace_EventType_EnterSection, section, _timer.GetTimestampNs()); 79 | } 80 | else 81 | { 82 | _didEventBufferRunOutOfMemory = true; 83 | } 84 | } 85 | 86 | 87 | void CSharpTrace::LeaveSection(const SectionInfo §ion) 88 | { 89 | auto event = _eventBuffer.Allocate(); 90 | 91 | 92 | if (event) 93 | { 94 | _initializeEvent(*event, KLab_Profiling_Trace_EventType_LeaveSection, section, _timer.GetTimestampNs()); 95 | } 96 | else 97 | { 98 | _didEventBufferRunOutOfMemory = true; 99 | } 100 | } 101 | 102 | 103 | bool CSharpTrace::_isEnabled() const 104 | { 105 | return _isTracing; 106 | } 107 | 108 | 109 | void CSharpTrace::_enable(KLab_Profiling_Trace_EventInfo *eventBuffer, const uint32_t eventBufferCapacity) 110 | { 111 | // Initialize state 112 | _timer.Reset(); 113 | _eventBuffer.Initialize(eventBuffer, eventBufferCapacity); 114 | 115 | _isTracing = true; 116 | } 117 | 118 | 119 | KLab_Profiling_Trace_TraceInfo CSharpTrace::_disable() 120 | { 121 | _isTracing = false; 122 | 123 | 124 | return 125 | { 126 | _timer.GetTimestampNs(), 127 | _eventBuffer.GetLength(), 128 | _didEventBufferRunOutOfMemory 129 | }; 130 | } 131 | 132 | 133 | CSharpTrace &GetCSharpTrace() 134 | { 135 | static CSharpTrace trace; 136 | 137 | 138 | return trace; 139 | } 140 | }}} 141 | 142 | 143 | // ----- // 144 | // TRACE // 145 | // ----- // 146 | 147 | KLab_Profiling_ErrorCode KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_TraceUtility_BeginTrace(KLab_Profiling_Trace_EventInfo *eventBuffer, const int32_t eventBufferSize) 148 | { 149 | auto &trace = KLab::Profiling::Trace::GetCSharpTrace(); 150 | 151 | 152 | // Validate state 153 | if (trace._isEnabled()) 154 | { 155 | return KLab_Profiling_ErrorCode_InvalidState; 156 | } 157 | 158 | 159 | // Validate arguments 160 | if (!eventBuffer || (eventBufferSize <= 0)) 161 | { 162 | return KLab_Profiling_ErrorCode_InvalidArgument; 163 | } 164 | 165 | 166 | trace._enable(eventBuffer, uint32_t(eventBufferSize)); 167 | 168 | 169 | return KLab_Profiling_ErrorCode_NoError; 170 | } 171 | 172 | 173 | KLab_Profiling_ErrorCode KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_TraceUtility_EndTrace(KLab_Profiling_Trace_TraceInfo *info) 174 | { 175 | auto &trace = KLab::Profiling::Trace::GetCSharpTrace(); 176 | 177 | 178 | // Validate state 179 | if (!trace._isEnabled()) 180 | { 181 | return KLab_Profiling_ErrorCode_InvalidState; 182 | } 183 | 184 | 185 | // Store trace result 186 | *info = trace._disable(); 187 | 188 | 189 | return KLab_Profiling_ErrorCode_NoError; 190 | } 191 | -------------------------------------------------------------------------------- /Plugins~/SourceFiles/Plugin.cpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #include 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #include 14 | #include 15 | 16 | 17 | // ------ // 18 | // PLUGIN // 19 | // ------ // 20 | 21 | namespace KLab { namespace Profiling { namespace Plugin 22 | { 23 | // Checks whether Android native is tracing 24 | // param contxt - Plugin context 25 | // @return true if tracing; false otherwise 26 | #if (KLAB_PROFILING_HAS_ATRACE) 27 | static inline bool _isATraceTracing(const PluginContext &context) 28 | { 29 | return (context.Trace.ATrace && context.Trace.ATrace->IsTracing()); 30 | } 31 | #else 32 | #define _isATraceTracing(context) (false) 33 | #endif 34 | 35 | // Checks whether C# is tracing 36 | // param contxt - Plugin context 37 | // @return true if tracing; false otherwise 38 | static inline bool _isCSharpTracing(const PluginContext &context) 39 | { 40 | return (context.Trace.CSharpTrace->IsTracing()); 41 | } 42 | 43 | // Checks whether extern is tracing 44 | // param contxt - Plugin context 45 | // @return true if tracing; false otherwise 46 | #if (KLAB_PROFILING_HAS_EXTERN_TRACE) 47 | static inline bool _isExternTracing(const PluginContext &context) 48 | { 49 | return (context.Trace.ExternTrace && context.Trace.ExternTrace->IsTracing()); 50 | } 51 | #else 52 | #define _isExternTracing(context) (false) 53 | #endif 54 | 55 | 56 | // Handles Unity marker event 57 | // @param descriptor - Marker descriptor 58 | // @param type - Event type 59 | // @param dataCount - Number of data 60 | // @param data - Data 61 | static void UNITY_INTERFACE_API _handleMarkerEvent(const UnityProfilerMarkerDesc *descriptor, UnityProfilerMarkerEventType type, uint16_t dataCount, const UnityProfilerMarkerData *data, void *_unused) 62 | { 63 | Utils::Utf8Buffer utf8Buffer; 64 | 65 | auto &context = GetPluginContext(); 66 | const auto group = context.Trace.SectionGroups.GetAtOrDefault(uint32_t(descriptor->categoryId)); 67 | Trace::SectionInfo section = 68 | { 69 | group.Name, 70 | descriptor->name, 71 | context.Utils->GetThreadID(), 72 | group.Color 73 | }; 74 | 75 | 76 | // Convert 'Profiler.Default' emitted UTF-16 to UTF-8 77 | if ((dataCount > 1) && (descriptor == context.Trace.DefaultMarkerDescriptor)) 78 | { 79 | utf8Buffer = context.Utils->ConvertUtf16ToUtf8(reinterpret_cast(data[1].ptr), (data[1].size / 2)); 80 | section.Name = utf8Buffer.CString; 81 | } 82 | 83 | 84 | // Forward event 85 | switch (type) 86 | { 87 | // Begin section 88 | case kUnityProfilerMarkerEventTypeBegin: 89 | { 90 | if (_isATraceTracing(context)) 91 | { 92 | context.Trace.ATrace->EnterSection(section.Name); 93 | } 94 | if (_isCSharpTracing(context)) 95 | { 96 | context.Trace.CSharpTrace->EnterSection(section); 97 | } 98 | 99 | if (_isExternTracing(context)) 100 | { 101 | context.Trace.ExternTrace->EnterSection(section); 102 | } 103 | break; 104 | } 105 | 106 | // End section 107 | case kUnityProfilerMarkerEventTypeEnd: 108 | { 109 | if (_isATraceTracing(context)) 110 | { 111 | context.Trace.ATrace->LeaveSection(); 112 | } 113 | if (_isCSharpTracing(context)) 114 | { 115 | context.Trace.CSharpTrace->LeaveSection(section); 116 | } 117 | 118 | if (_isExternTracing(context)) 119 | { 120 | context.Trace.ExternTrace->LeaveSection(section); 121 | } 122 | break; 123 | } 124 | } 125 | } 126 | 127 | 128 | // Handles category creation 129 | // @param descriptor - Category descriptor 130 | static void UNITY_INTERFACE_API _handleCreateCategory(const UnityProfilerCategoryDesc *descriptor, void *_unused) 131 | { 132 | Trace::SectionGroupInfo group; 133 | 134 | auto &context = GetPluginContext(); 135 | 136 | 137 | group.Name = descriptor->name; 138 | group.Color = descriptor->rgbaColor; 139 | 140 | 141 | context.Trace.SectionGroups.Add(group); 142 | } 143 | 144 | 145 | // Handles Unity marker creation event 146 | // @param descriptor - Marker descriptor 147 | static void UNITY_INTERFACE_API _handleCreateMarker(const UnityProfilerMarkerDesc *descriptor, void *_unused) 148 | { 149 | // Checks whether descriptor is default marker descriptor 150 | // @param descriptor - Marker descriptor 151 | // @return tre if default; false otherwise 152 | auto isDefaultMarkerDescriptor = [](const UnityProfilerMarkerDesc &descriptor) 153 | { 154 | auto lhs = "Profiler.Default"; 155 | auto rhs = descriptor.name; 156 | 157 | 158 | for (;; ++lhs, ++rhs) 159 | { 160 | if (*lhs != *rhs) 161 | { 162 | return false; 163 | } 164 | if (!*lhs) 165 | { 166 | break; 167 | } 168 | } 169 | 170 | 171 | return true; 172 | }; 173 | 174 | 175 | auto &context = GetPluginContext(); 176 | 177 | 178 | // Store default marker descriptor 179 | if (!context.Trace.DefaultMarkerDescriptor && isDefaultMarkerDescriptor(*descriptor)) 180 | { 181 | context.Trace.DefaultMarkerDescriptor = descriptor; 182 | } 183 | 184 | 185 | // Register callback 186 | context.Unity.ProfilerCallbacks->RegisterMarkerEventCallback(descriptor, _handleMarkerEvent, _unused); 187 | } 188 | 189 | 190 | // Updates context 191 | static void _update() 192 | { 193 | auto &context = GetPluginContext(); 194 | const bool shouldRegisterCallbacks = (_isATraceTracing(context) || _isCSharpTracing(context) || _isExternTracing(context)); 195 | static bool hasRegisteredCallbacks = false; 196 | 197 | 198 | // Register/Unregister callbacks dynamically 199 | if (shouldRegisterCallbacks != hasRegisteredCallbacks) 200 | { 201 | if (shouldRegisterCallbacks) 202 | { 203 | context.Unity.ProfilerCallbacks->RegisterCreateMarkerCallback(_handleCreateMarker, nullptr); 204 | } 205 | else 206 | { 207 | context.Unity.ProfilerCallbacks->UnregisterCreateMarkerCallback(_handleCreateMarker, nullptr); 208 | context.Unity.ProfilerCallbacks->UnregisterMarkerEventCallback(nullptr, _handleMarkerEvent, nullptr); 209 | } 210 | 211 | 212 | hasRegisteredCallbacks = shouldRegisterCallbacks; 213 | } 214 | } 215 | }}} 216 | 217 | 218 | // ------ // 219 | // PLUGIN // 220 | // ------ // 221 | 222 | KLab_Profiling_ErrorCode UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API KLab_Profiling_Plugin_Initialize() 223 | { 224 | // Assert plugin context to be created 225 | return (KLab::Profiling::Plugin::GetPluginContext() ? KLab_Profiling_ErrorCode_NoError : KLab_Profiling_ErrorCode_NotAvailable); 226 | } 227 | 228 | 229 | void KLAB_PROFILING_CSHARP_INTERFACE KLab_Profiling_Plugin_Update() 230 | { 231 | using namespace KLab::Profiling::Plugin; 232 | 233 | 234 | // Early out if context invailed 235 | if (!GetPluginContext()) 236 | { 237 | return; 238 | } 239 | 240 | 241 | _update(); 242 | } 243 | 244 | 245 | void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces *unity) 246 | { 247 | auto &context = KLab::Profiling::Plugin::CreatePluginContext(unity); 248 | 249 | 250 | // Prevent 'unused' warnings 251 | (void)context; 252 | } 253 | 254 | 255 | void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() 256 | { 257 | using namespace KLab::Profiling::Plugin; 258 | 259 | 260 | auto &context = GetPluginContext(); 261 | 262 | 263 | // Early out if context invailed 264 | if (!context) 265 | { 266 | return; 267 | } 268 | 269 | 270 | // Unregister from Unity 271 | context.Unity.ProfilerCallbacks->UnregisterMarkerEventCallback(nullptr, _handleMarkerEvent, nullptr); 272 | context.Unity.ProfilerCallbacks->UnregisterCreateMarkerCallback(_handleCreateMarker, nullptr); 273 | context.Unity.ProfilerCallbacks->UnregisterCreateCategoryCallback(_handleCreateCategory, nullptr); 274 | 275 | 276 | // Release context 277 | context.Unload(); 278 | } 279 | -------------------------------------------------------------------------------- /Plugins~/Internal/KLab/Profiling/Internal.hpp: -------------------------------------------------------------------------------- 1 | // -------------------------------------------------------------------------------------------- // 2 | // Copyright (c) KLab Inc.. All rights reserved. // 3 | // Licensed under the MIT License. See 'LICENSE' in the project root for license information. // 4 | // -------------------------------------------------------------------------------------------- // 5 | 6 | #pragma once 7 | 8 | 9 | // -------- // 10 | // INCLUDES // 11 | // -------- // 12 | 13 | #include 14 | #include 15 | 16 | #include 17 | #include 18 | 19 | struct IUnityInterfaces; 20 | struct IUnityProfilerCallbacks; 21 | struct UnityProfilerMarkerDesc; 22 | 23 | 24 | // ------- // 25 | // HELPERS // 26 | // ------- // 27 | 28 | namespace KLab { namespace Profiling 29 | { 30 | /// Non-growing buffer with thread-safe allocate function 31 | template 32 | struct AtomicBuffer final 33 | { 34 | /// Gets base address 35 | /// @return the base address 36 | T *GetBase() 37 | { 38 | return _base; 39 | } 40 | 41 | /// Gets number of data currently allocated 42 | /// @return the number of data allocated 43 | uint32_t GetLength() const 44 | { 45 | return _position; 46 | } 47 | 48 | /// Initializes buffer 49 | /// @param base - Buffer base address 50 | /// @param capacity - Buffer capacity in data 51 | void Initialize(T *base, const uint32_t capacity) 52 | { 53 | _base = base; 54 | _capacity = capacity; 55 | _position = 0; 56 | } 57 | 58 | /// Allocates datum 59 | /// @return a valid pointer to allocated datum on success; null otherwise 60 | T *Allocate() 61 | { 62 | const uint32_t index = _position++; 63 | 64 | 65 | return ((index < _capacity) ? (_base + index) : nullptr); 66 | } 67 | 68 | /// Rebases and resets buffer (assuming same capacity) 69 | /// @param base - New base address 70 | void RebaseAndReset(T *base) 71 | { 72 | Initialize(base, _capacity); 73 | } 74 | 75 | // Base address 76 | T *_base = nullptr; 77 | // Capacity 78 | uint32_t _capacity = 0; 79 | // Position 80 | std::atomic _position = { 0 }; 81 | }; 82 | 83 | 84 | /// Array-like list with fixed capacity 85 | template 86 | struct FixedCapacityList final 87 | { 88 | /// Tries to get datum at index 89 | /// @param index - Index of datum to get 90 | /// @return copy of datum at given index if available; default datum otherwise 91 | const T GetAtOrDefault(const uint32_t index) const 92 | { 93 | T default_; 94 | 95 | 96 | return (index < _position ? _base[index] : default_); 97 | } 98 | 99 | 100 | /// Adds datum 101 | /// @returns true on success; false on out-of-memory 102 | bool Add(const T &datum) 103 | { 104 | const uint32_t index = _position++; 105 | 106 | 107 | if (index >= _capacity) 108 | { 109 | return false; 110 | } 111 | 112 | 113 | _base[index] = datum; 114 | 115 | 116 | return true; 117 | } 118 | 119 | 120 | // Base address 121 | T _base[N]; 122 | // Capacity 123 | static constexpr uint32_t _capacity = N; 124 | // Position 125 | uint32_t _position = 0; 126 | }; 127 | 128 | 129 | /// Stopwatch utility 130 | struct Stopwatch final 131 | { 132 | /// Gets offset since last frame flip 133 | /// @return the offset since last frame flip in nanoseconds 134 | inline uint64_t GetTimestampNs() const 135 | { 136 | // Be explicit about nanoseconds 137 | std::chrono::nanoseconds offset = (std::chrono::high_resolution_clock::now() - _lastFlip); 138 | 139 | 140 | return uint64_t(offset.count()); 141 | } 142 | 143 | /// Resets timer 144 | inline void Reset() 145 | { 146 | _lastFlip = std::chrono::high_resolution_clock::now(); 147 | } 148 | 149 | // Time at last flip 150 | std::chrono::high_resolution_clock::time_point _lastFlip; 151 | }; 152 | 153 | 154 | namespace Trace 155 | { 156 | /// Info on a group of sections 157 | struct SectionGroupInfo final 158 | { 159 | /// Group name 160 | const char *Name = "\0"; 161 | /// Group RGBA color 162 | uint32_t Color = 0x2d89ef; 163 | }; 164 | } 165 | }} 166 | 167 | 168 | // ------------------- // 169 | // ANDOID NATIVE TRACE // 170 | // ------------------- // 171 | 172 | namespace KLab { namespace Profiling { namespace Trace 173 | { 174 | /// Android native trace interface 175 | struct ATrace final 176 | { 177 | /// Flags whether should trace 178 | /// @return whether tracer is tracing 179 | bool (*IsTracing)(); 180 | /// Handles section enter 181 | /// @param name - Section name 182 | void (*EnterSection)(const char *name); 183 | /// Handles section leave 184 | void (*LeaveSection)(); 185 | /// Unloads interface 186 | void Unload(); 187 | 188 | // Tries initializing interface 189 | ATrace(); 190 | 191 | // Converts to bool 192 | operator bool() const 193 | { 194 | return (IsTracing != nullptr); 195 | } 196 | 197 | // 'libandroid.so' handle 198 | void *_libAndroid; 199 | }; 200 | 201 | 202 | /// Tries to get Android native trace interface 203 | /// @return the interface if available; null otherwise 204 | ATrace *TryGetATrace(); 205 | }}} 206 | 207 | 208 | // -------- // 209 | // C# TRACE // 210 | // -------- // 211 | 212 | namespace KLab { namespace Profiling { namespace Trace 213 | { 214 | /// C# trace interface 215 | struct CSharpTrace final 216 | { 217 | /// Flags whether should trace 218 | /// @return whether tracer is tracing 219 | bool IsTracing() const; 220 | /// Ticks interface 221 | void Flip(); 222 | /// Handles entering section enter 223 | /// @param section - Info on section 224 | void EnterSection(const SectionInfo §ion); 225 | // Handles section leave 226 | /// @param section - Info on section 227 | void LeaveSection(const SectionInfo §ion); 228 | 229 | // Frame time 230 | Stopwatch _timer; 231 | // Trace event buffer 232 | AtomicBuffer _eventBuffer; 233 | // Flag whether to trace current frame 234 | bool _isTracing = false; 235 | // Flag whether event buffer ran full 236 | bool _didEventBufferRunOutOfMemory = false; 237 | 238 | // Flags whether tracing is enabled 239 | // @return true if enabled; false otherwise 240 | bool _isEnabled() const; 241 | // Enables tracing (expecting valid arguments) 242 | // @param eventBuffer - Trace frame flip function 243 | // @param eventBufferCapacity - Event buffer capacity 244 | void _enable(KLab_Profiling_Trace_EventInfo *eventBuffer, const uint32_t eventBufferCapacity); 245 | // Disables tracing 246 | // @return Info on trace 247 | KLab_Profiling_Trace_TraceInfo _disable(); 248 | 249 | // Defaults construction 250 | CSharpTrace() = default; 251 | // Prevents copy construction 252 | CSharpTrace(const CSharpTrace &) = delete; 253 | // Prevents move construction 254 | CSharpTrace(CSharpTrace &&) = delete; 255 | }; 256 | 257 | 258 | /// Get C# trace interface 259 | /// @return the interface 260 | CSharpTrace &GetCSharpTrace(); 261 | }}} 262 | 263 | 264 | // ------------ // 265 | // EXTERN TRACE // 266 | // ------------ // 267 | 268 | namespace KLab { namespace Profiling { namespace Trace 269 | { 270 | /// Tries to get extern trace interface 271 | /// @return the interface if available; null otherwise 272 | inline IExternTrace *TryGetExternTrace() 273 | { 274 | static IExternTrace *trace = nullptr; 275 | 276 | 277 | #if KLAB_PROFILING_HAS_EXTERN_TRACE 278 | if (!trace) 279 | { 280 | trace = LoadExternTrace(); 281 | } 282 | #endif 283 | 284 | 285 | return trace; 286 | } 287 | }}} 288 | 289 | 290 | // ----- // 291 | // UTILS // 292 | // ----- // 293 | 294 | namespace KLab { namespace Profiling { namespace Utils 295 | { 296 | /// Utility functions interface 297 | typedef IExternUtils IUtils; 298 | 299 | 300 | /// Gets utility interface 301 | /// @return the singleton interface 302 | IUtils &GetUtils(); 303 | }}} 304 | 305 | 306 | // -------------- // 307 | // PLUGIN CONTEXT // 308 | // -------------- // 309 | 310 | namespace KLab { namespace Profiling { namespace Plugin 311 | { 312 | /// Plugin context 313 | struct PluginContext final 314 | { 315 | 316 | 317 | 318 | /// Unity context 319 | struct 320 | { 321 | /// Unity interfaces 322 | IUnityInterfaces *Interfaces = nullptr; 323 | /// Profiler callbacks 324 | IUnityProfilerCallbacks *ProfilerCallbacks = nullptr; 325 | } 326 | Unity; 327 | // Trace context 328 | struct 329 | { 330 | /// Default marker descriptor 331 | const UnityProfilerMarkerDesc *DefaultMarkerDescriptor = nullptr; 332 | // [Optional] Android native trace interface 333 | Trace::ATrace *ATrace = nullptr; 334 | // C# trace interface 335 | Trace::CSharpTrace *CSharpTrace = nullptr; 336 | // [Optional] Extern trace interface 337 | Trace::IExternTrace *ExternTrace = nullptr; 338 | // Marker groups 339 | // INV How much capacity is needed? 340 | FixedCapacityList SectionGroups; 341 | } 342 | Trace; 343 | // Utilities 344 | Utils::IUtils *Utils; 345 | 346 | /// Unloads context 347 | void Unload(); 348 | 349 | // Defaults construction 350 | PluginContext() = default; 351 | // Prevents copy construction 352 | PluginContext(const PluginContext &) = delete; 353 | // Prevents move construction 354 | PluginContext(PluginContext &&) = delete; 355 | 356 | // Converts to bool 357 | // @return true if context valid; false otherwise 358 | operator bool() const 359 | { 360 | return (Unity.ProfilerCallbacks != nullptr); 361 | } 362 | }; 363 | 364 | 365 | /// Creates plugin context (expecting valid arguments) 366 | /// @param unity - Unity interfaces 367 | /// @return the singleton instance 368 | PluginContext &CreatePluginContext(IUnityInterfaces *unity); 369 | 370 | /// Gets plugin context 371 | /// @return the singleton context 372 | PluginContext &GetPluginContext(); 373 | }}} 374 | --------------------------------------------------------------------------------