using System; using System.Collections.Generic; using System.Diagnostics; using System.Runtime.InteropServices; using System.Text; using Unity.Collections.LowLevel.Unsafe; using Unity.Profiling; using UnityEngine.Profiling; using UnityEngine; /// /// Profiler Stats reporting helper class. Stores all adaptive performance counters and helper functions. /// public static class AdaptivePerformanceProfilerStats { /// /// Profiler Category is set to scripts for Adaptive Performance. /// public static readonly ProfilerCategory AdaptivePerformanceProfilerCategory = ProfilerCategory.Scripts; /// /// Profiler counter to report cpu frametime. /// public static ProfilerCounter CurrentCPUCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "CPU frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report cpu average frametime. /// public static ProfilerCounter AvgCPUCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "CPU avg frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report gpu frametime. /// public static ProfilerCounter CurrentGPUCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "GPU frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report gpu average frametime. /// public static ProfilerCounter AvgGPUCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "GPU avg frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report cpu performance level. /// public static ProfilerCounter CurrentCPULevelCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "CPU performance level", ProfilerMarkerDataUnit.Count); /// /// Profiler counter to report gpu performance level. /// public static ProfilerCounter CurrentGPULevelCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "GPU performance level", ProfilerMarkerDataUnit.Count); /// /// Profiler counter to report frametime. /// public static ProfilerCounter CurrentFrametimeCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report average frametime. /// public static ProfilerCounter AvgFrametimeCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Avg frametime", ProfilerMarkerDataUnit.TimeNanoseconds); /// /// Profiler counter to report the thermal warning level. /// public static ProfilerCounter WarningLevelCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Thermal Warning Level", ProfilerMarkerDataUnit.Count); /// /// Profiler counter to report the temperature level. /// public static ProfilerCounter TemperatureLevelCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Temperature Level", ProfilerMarkerDataUnit.Count); /// /// Profiler counter to report the temperature trend. /// public static ProfilerCounter TemperatureTrendCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Temperature Trend", ProfilerMarkerDataUnit.Count); /// /// Profiler counter to report the bottleneck. /// public static ProfilerCounter BottleneckCounter = new ProfilerCounter(AdaptivePerformanceProfilerCategory, "Bottleneck", ProfilerMarkerDataUnit.Count); /// /// GUID for the Adaptive Performance Profile Module definition. /// public static readonly Guid kAdaptivePerformanceProfilerModuleGuid = new Guid("42c5aeb7-fb77-4172-a384-34063f1bd332"); /// /// The Scaler data tag defines a tag for the scalers to send them via the emit frame data function. /// public static readonly int kScalerDataTag = 0; static Dictionary scalerInfos = new Dictionary(); /// /// ScalerInfo is a struct used to collect and send scaler info to the profile collectively. /// [StructLayout(LayoutKind.Sequential)] public unsafe struct ScalerInfo { /// /// The name of the scaler. 320 characters max. /// public fixed byte scalerName[320]; /// /// If the scaler is currently enabled. /// public uint enabled; /// /// The override state of the scaler. /// public int overrideLevel; /// /// The current level of the scaler. /// public int currentLevel; /// /// The maximum level of the scaler. /// public int maxLevel; /// /// The actual scale of the scaler. /// public float scale; /// /// State if the scaler is currently applied. /// public uint applied; } /// /// Adaptive Performance sends scaler data to the profiler each frame. It is collected from multiple places with this method and flushed once with . /// /// The name of the scaler. 320 characters max. /// If the scaler is currently enabled. /// The override state of the scaler. /// The current level of the scaler. /// The actual scale of the scaler. /// If the scaler is currently applied. /// The maximum level of the scaler. [Conditional("ENABLE_PROFILER")] public static void EmitScalerDataToProfilerStream(string scalerName, bool enabled, int overrideLevel, int currentLevel, float scale, bool applied, int maxLevel) { if (!Profiler.enabled || scalerName.Length == 0) return; ScalerInfo scalerInfo; bool existingInfo = scalerInfos.TryGetValue(scalerName, out scalerInfo); if (!existingInfo) scalerInfo = new ScalerInfo(); byte[] scalerNameBytes = Encoding.ASCII.GetBytes(scalerName); scalerInfo.enabled = (uint)(enabled ? 1 : 0); scalerInfo.overrideLevel = overrideLevel; scalerInfo.currentLevel = currentLevel; scalerInfo.scale = scale; scalerInfo.maxLevel = maxLevel; scalerInfo.applied = (uint)(applied ? 1 : 0); unsafe { fixed(byte* pSource = scalerNameBytes) { UnsafeUtility.MemCpy(scalerInfo.scalerName, pSource, scalerNameBytes.Length); } } if (!existingInfo) scalerInfos.Add(scalerName, scalerInfo); else scalerInfos[scalerName] = scalerInfo; } /// /// Flushes the Adaptive Performance scaler data for this frame. Used in conjunction with . /// public static void FlushScalerDataToProfilerStream() { ScalerInfo[] arr = new ScalerInfo[scalerInfos.Count]; scalerInfos.Values.CopyTo(arr, 0); Profiler.EmitFrameMetaData(kAdaptivePerformanceProfilerModuleGuid, kScalerDataTag, arr); } }