WuhuIslandTesting/Library/PackageCache/com.unity.xr.oculus@4.0.0/Runtime/OculusPerformance.cs
2025-01-07 02:06:59 +01:00

607 lines
20 KiB
C#

using System;
using System.Runtime.InteropServices;
using UnityEngine;
#if ENABLE_VR || PACKAGE_DOCS_GENERATION
using System.Collections.Generic;
using UnityEngine.XR;
using XRStats = UnityEngine.XR.Provider.XRStats;
#endif
namespace Unity.XR.Oculus
{
public static class Performance
{
/// <summary>
/// Set the CPU Level for the device
/// </summary>
/// <param name="level">
/// Allowable values are integers in the range 0 - 4 (inclusive). A value of 0 is the lowest performance level but is the most power efficient.
/// Please note: as this is a hint, it may not be immediately reflected by the system.
/// </param>
/// <returns>
/// True if we have no errors returned by the native function. We return false when the native function returns a failure condition.
/// Check the log for more information.
/// </returns>
public static bool TrySetCPULevel(int level)
{
return (NativeMethods.SetCPULevel(level) == 0);
}
/// <summary>
/// Set the GPU performance level
/// </summary>
/// <param name="level">
/// Allowable values are integers in the range 0 - 4 (inclusive). A value of 0 is the lowest performance level but is the most power efficient.
/// Please note: as this is a hint, it may not be immediately reflected by the system.
/// </param>
/// <returns>
/// True if we have no errors returned by the native function. We return false when the native function returns a failure condition. Check
/// the log for more information.
/// </returns>
public static bool TrySetGPULevel(int level)
{
return (NativeMethods.SetGPULevel(level) == 0);
}
private static float[] cachedDisplayAvailableFrequencies = null;
/// <summary>
/// Get an array of available display frequencies supported by this hardware.
/// </summary>
public static bool TryGetAvailableDisplayRefreshRates(out float[] refreshRates)
{
if (cachedDisplayAvailableFrequencies == null || cachedDisplayAvailableFrequencies.Length == 0)
{
cachedDisplayAvailableFrequencies = new float[0];
int numFrequencies = 0;
if (NativeMethods.GetDisplayAvailableFrequencies(IntPtr.Zero, ref numFrequencies) && numFrequencies > 0)
{
int size = sizeof(float) * numFrequencies;
IntPtr ptr = Marshal.AllocHGlobal(size);
if (NativeMethods.GetDisplayAvailableFrequencies(ptr, ref numFrequencies) && numFrequencies > 0)
{
cachedDisplayAvailableFrequencies = new float[numFrequencies];
Marshal.Copy(ptr, cachedDisplayAvailableFrequencies, 0, numFrequencies);
}
Marshal.FreeHGlobal(ptr);
}
}
refreshRates = cachedDisplayAvailableFrequencies;
return (cachedDisplayAvailableFrequencies.Length > 0);
}
/// <summary>
/// Set the current display frequency.
/// </summary>
public static bool TrySetDisplayRefreshRate(float refreshRate)
{
return NativeMethods.SetDisplayFrequency(refreshRate);
}
/// <summary>
/// Get the current display frequency.
/// </summary>
public static bool TryGetDisplayRefreshRate(out float refreshRate)
{
return NativeMethods.GetDisplayFrequency(out refreshRate);
}
}
public class Stats
{
private static IntegratedSubsystem m_Display;
private static string m_PluginVersion = string.Empty;
/// <summary>
/// Gets the version of OVRPlugin currently in use. Format: "major.minor.release"
/// </summary>
public static string PluginVersion
{
get
{
if (string.Equals(string.Empty, m_PluginVersion))
{
byte[] buf = new byte[256];
NativeMethods.GetOVRPVersion(buf);
var end = Array.IndexOf<byte>(buf, 0);
m_PluginVersion = System.Text.Encoding.ASCII.GetString(buf, 0, end);
}
return m_PluginVersion;
}
}
/// <summary>
/// Provides performance statistics useful for adaptive performance systems. Not every stat is supported on every Oculus platform and will always return a value of 0 if unsupported.
/// </summary>
public static class AdaptivePerformance
{
/// <summary>
/// Reports the time the application spent on the GPU last frame in seconds.
/// </summary>
public static float GPUAppTime
{
get
{
#if ENABLE_VR
float val;
((XRDisplaySubsystem) GetOculusDisplaySubsystem()).TryGetAppGPUTimeLastFrame(out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the time the compositor spent on the GPU last frame in seconds.
/// </summary>
public static float GPUCompositorTime
{
get
{
#if ENABLE_VR
float val;
((XRDisplaySubsystem) GetOculusDisplaySubsystem()).TryGetCompositorGPUTimeLastFrame(out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the latency from when the last predicted tracking information was queried by the application to the moment the middle scaline of the target frame is illuminated on the display.
/// </summary>
public static float MotionToPhoton
{
get
{
#if ENABLE_VR
float val;
((XRDisplaySubsystem) GetOculusDisplaySubsystem()).TryGetMotionToPhoton(out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the display's refresh rate in frames per second
/// </summary>
[Obsolete("RefreshRate is deprecated. Use Performance.TryGetDisplayRefreshRate instead.", false)]
public static float RefreshRate
{
get
{
#if ENABLE_VR
float val;
((XRDisplaySubsystem) GetOculusDisplaySubsystem()).TryGetDisplayRefreshRate(out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Gets the current battery temperature in degrees Celsius.
/// </summary>
public static float BatteryTemp
{
get
{
#if ENABLE_VR
float batteryTemp;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "batteryTemperature", out batteryTemp);
return batteryTemp;
#else
return default;
#endif
}
}
/// <summary>
/// Gets the current available battery charge, ranging from 0.0 (empty) to 1.0 (full).
/// </summary>
public static float BatteryLevel
{
get
{
#if ENABLE_VR
float batteryLevel;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "batteryLevel", out batteryLevel);
return batteryLevel;
#else
return default;
#endif
}
}
/// <summary>
/// If true, the system is running in a reduced performance mode to save power.
/// </summary>
public static bool PowerSavingMode
{
get
{
#if ENABLE_VR
float powerSavingMode;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "powerSavingMode", out powerSavingMode);
return !(powerSavingMode == 0.0f);
#else
return default;
#endif
}
}
/// <summary>
/// Returns the recommended amount to scale GPU work in order to maintain framerate.
/// Can be used to adjust viewportScale and textureScale
/// </summary>
public static float AdaptivePerformanceScale
{
get
{
#if ENABLE_VR
float performanceScale;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "adaptivePerformanceScale", out performanceScale);
return performanceScale;
#else
return default;
#endif
}
}
/// <summary>
/// Gets the current CPU performance level, integer in the range 0 - 3.
/// </summary>
public static int CPULevel
{
get
{
#if ENABLE_VR
float cpuLevel;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "cpuLevel", out cpuLevel);
return (int) cpuLevel;
#else
return default;
#endif
}
}
/// <summary>
/// Gets the current GPU performance level, integer in the range 0 - 3.
/// </summary>
public static int GPULevel
{
get
{
#if ENABLE_VR
float gpuLevel;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "gpuLevel", out gpuLevel);
return (int) gpuLevel;
#else
return default;
#endif
}
}
}
/// <summary>
/// Provides additional perf metrics. These stats will not be tracked unless the user makes a PerfMetrics.EnablePerfMetrics(true) method call. Not every stat is supported on every Oculus platform and will always return a value of 0 if unsupported.
/// <para/><b>Note:</b> PerfMetrics stats will return 0 when using the OpenXR runtime. The suggested replacement is to use the profiling tools available via the Oculus Developer Hub: https://developer.oculus.com/documentation/unity/ts-odh-logs-metrics/
/// </summary>
public static class PerfMetrics
{
/// <summary>
/// Reports the time the application spent on the CPU last frame in seconds.
/// </summary>
public static float AppCPUTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.appcputime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the time the application spen on the GPU last frame in seconds.
/// </summary>
public static float AppGPUTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.appgputime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the time the compositor spent on the CPU last frame in seconds.
/// </summary>
public static float CompositorCPUTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.compositorcputime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the time the compositor spent on the GPU last frame in seconds.
/// </summary>
public static float CompositorGPUTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.compositorgputime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the GPU utilization as a value from 0.0 - 1.0.
/// </summary>
public static float GPUUtilization
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.gpuutil", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the average CPU utilization as a value from 0.0 - 1.0.
/// </summary>
public static float CPUUtilizationAverage
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.cpuutilavg", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the worst CPU utilization as a value from 0.0 - 1.0.
/// </summary>
public static float CPUUtilizationWorst
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.cpuutilworst", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the CPU clock frequency
/// </summary>
public static float CPUClockFrequency
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.cpuclockfreq", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the GPU clock frequency
/// </summary>
public static float GPUClockFrequency
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "perfmetrics.gpuclockfreq", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Enable or disable provider tracking perf metrics. Perf metrics are disabled by default.
/// </summary>
public static void EnablePerfMetrics(bool enable)
{
NativeMethods.EnablePerfMetrics(enable);
}
}
/// <summary>
/// Provides additional application metrics. These metrics will not be tracked unless the user makes a AppMetrics.EnableAppMetrics(true) method call.
/// <para/><b>Note:</b> AppMetrics are deprecated and currently return 0 on all Oculus runtimes. The suggested replacement is to use the profiling tools available via the Oculus Developer Hub: https://developer.oculus.com/documentation/unity/ts-odh-logs-metrics/
/// </summary>
public static class AppMetrics
{
public static float AppQueueAheadTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.appqueueahead", out val);
return val;
#else
return default;
#endif
}
}
public static float AppCPUElapsedTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.cpuelapsedtime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the number of frames dropped by the compositor.
/// </summary>
public static float CompositorDroppedFrames
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.compositordroppedframes", out val);
return val;
#else
return default;
#endif
}
}
public static float CompositorLatency
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.compositorlatency", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the time the compositor spent on the CPU last frame in seconds.
/// </summary>
public static float CompositorCPUTime
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.compositorcputime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the total time from beginning of the main thread until compositor frame submission.
/// </summary>
public static float CPUStartToGPUEnd
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.compositorcpustartgpuendelapsedtime", out val);
return val;
#else
return default;
#endif
}
}
/// <summary>
/// Reports the total time from compositor frame submission until the frame sync point.
/// </summary>
public static float GPUEndToVsync
{
get
{
#if ENABLE_VR
float val;
XRStats.TryGetStat(GetOculusDisplaySubsystem(), "appstats.compositorgpuendtovsyncelapsedtime", out val);
return val;
#else
return default;
#endif
}
}
public static void EnableAppMetrics(bool enable)
{
NativeMethods.EnableAppMetrics(enable);
}
}
private static IntegratedSubsystem GetOculusDisplaySubsystem()
{
if (m_Display != null)
return m_Display;
#if ENABLE_VR
List<XRDisplaySubsystem> displays = new List<XRDisplaySubsystem>();
SubsystemManager.GetInstances(displays);
foreach (XRDisplaySubsystem xrDisplaySubsystem in displays)
{
if (xrDisplaySubsystem.SubsystemDescriptor.id == "oculus display" && xrDisplaySubsystem.running)
{
m_Display = xrDisplaySubsystem;
return m_Display;
}
}
#endif
Debug.LogError("No active Oculus display subsystem was found.");
return m_Display;
}
}
}