nuclear@0: /************************************************************************************ nuclear@0: nuclear@0: Filename : CAPI_LatencyStatistics.h nuclear@0: Content : Record latency statistics during rendering nuclear@0: Created : Sept 23, 2014 nuclear@0: Authors : Chris Taylor, Kevin Jenkins nuclear@0: nuclear@0: Copyright : Copyright 2014 Oculus VR, LLC All Rights reserved. nuclear@0: nuclear@0: Licensed under the Oculus VR Rift SDK License Version 3.2 (the "License"); nuclear@0: you may not use the Oculus VR Rift SDK except in compliance with the License, nuclear@0: which is provided at the time of installation or download, or which nuclear@0: otherwise accompanies this software in either electronic or hard copy form. nuclear@0: nuclear@0: You may obtain a copy of the License at nuclear@0: nuclear@0: http://www.oculusvr.com/licenses/LICENSE-3.2 nuclear@0: nuclear@0: Unless required by applicable law or agreed to in writing, the Oculus VR SDK nuclear@0: distributed under the License is distributed on an "AS IS" BASIS, nuclear@0: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. nuclear@0: See the License for the specific language governing permissions and nuclear@0: limitations under the License. nuclear@0: nuclear@0: ************************************************************************************/ nuclear@0: nuclear@0: #ifndef OVR_CAPI_LatencyStatistics_h nuclear@0: #define OVR_CAPI_LatencyStatistics_h nuclear@0: nuclear@0: #include "../OVR_CAPI.h" nuclear@0: #include "../Kernel/OVR_Timer.h" nuclear@0: #include "../Kernel/OVR_Lockless.h" nuclear@0: #include "../Kernel/OVR_SysFile.h" nuclear@0: #include "CAPI_FrameTimeManager.h" nuclear@0: nuclear@0: namespace OVR { namespace CAPI { nuclear@0: nuclear@0: nuclear@0: // Define epoch period for lag statistics nuclear@0: #define OVR_LAG_STATS_EPOCH 1.0 /* seconds */ nuclear@0: // Define seconds without frames before resetting stats nuclear@0: #define OVR_LAG_STATS_RESET_LIMIT 2.0 /* seconds */ nuclear@0: nuclear@0: nuclear@0: //------------------------------------------------------------------------------------- nuclear@0: // ***** LatencyStatisticsResults nuclear@0: nuclear@0: // Results from statistics collection nuclear@0: struct LatencyStatisticsResults nuclear@0: { nuclear@0: // Number of seconds of data represented by these statistics. nuclear@0: double IntervalSeconds; nuclear@0: nuclear@0: // Frames per second during the epoch. nuclear@0: double FPS; nuclear@0: nuclear@0: // Measures average time for EndFrame() call over each of the frames. nuclear@0: double EndFrameExecutionTime; nuclear@0: nuclear@0: // Measures the time between first scanline and first pose request before app starts rendering eyes. nuclear@0: float LatencyRender; nuclear@0: nuclear@0: // Measures the time between first scanline and distortion/timewarp rendering. nuclear@0: float LatencyTimewarp; nuclear@0: nuclear@0: // Time between Present() call and photon emission from first scanline of screen nuclear@0: float LatencyPostPresent; nuclear@0: nuclear@0: // Measures the time from receiving the camera frame until vision CPU processing completes. nuclear@0: double LatencyVisionProc; nuclear@0: nuclear@0: // Measures the time from exposure until the pose is available for the frame, including processing time. nuclear@0: double LatencyVisionFrame; nuclear@0: }; nuclear@0: nuclear@0: //----------------------------------------------------------------------------- nuclear@0: typedef Delegate1 LatencyStatisticsSlot; nuclear@0: nuclear@0: // ***** LatencyStatisticsObserver nuclear@0: class LatencyStatisticsCSV nuclear@0: { nuclear@0: public: nuclear@0: LatencyStatisticsCSV(); nuclear@0: ~LatencyStatisticsCSV(); nuclear@0: bool Start(String fileName, String userData1); nuclear@0: bool Stop(); nuclear@0: void OnResults(LatencyStatisticsResults *results); nuclear@0: nuclear@0: // Internal nuclear@0: void WriteHeaderV1(); nuclear@0: void WriteResultsV1(LatencyStatisticsResults *results); nuclear@0: ObserverScope* GetObserver() { return &_Observer; } nuclear@0: nuclear@0: protected: nuclear@0: ObserverScope _Observer; nuclear@0: String Guid, UserData1; nuclear@0: String FileName; nuclear@0: OVR::SysFile _File; nuclear@0: String OS, OSVersion, ProcessInfo, DisplayDriverVersion, CameraDriverVersion, GPUVersion; nuclear@0: }; nuclear@0: nuclear@0: //----------------------------------------------------------------------------- nuclear@0: // ***** LatencyStatisticsCalculator nuclear@0: nuclear@0: // Calculator for latency statistics nuclear@0: class LagStatsCalculator nuclear@0: { nuclear@0: // Statistics instrumentation inputs: nuclear@0: nuclear@0: // Timestamp when the EndFrame() call started executing nuclear@0: double EndFrameStartTime; nuclear@0: // Timestamp when the EndFrame() call finished executing nuclear@0: double EndFrameEndTime; nuclear@0: nuclear@0: // Latency statistics for the epoch nuclear@0: LatencyStatisticsResults latencyStatisticsData; nuclear@0: nuclear@0: // Last latency data nuclear@0: // float LatencyData[3]; // render, timewarp, median post-present nuclear@0: nuclear@0: // Last vision processing frame counter number nuclear@0: uint32_t LastCameraFrameCounter; nuclear@0: nuclear@0: // Running statistics: nuclear@0: nuclear@0: void resetPerfStats(double resetTime = 0.); nuclear@0: nuclear@0: // Start of the current statistics epoch nuclear@0: double EpochBegin; nuclear@0: // Count of frames in this stats epoch, measured at EndFrame() nuclear@0: int FrameCount; nuclear@0: // Sum of end frame durations for this stats epoch nuclear@0: //double EndFrameSum; nuclear@0: nuclear@0: // Sum of latencies nuclear@0: // double LatencySum[3]; nuclear@0: nuclear@0: // Sum of vision processing times nuclear@0: //double VisionProcSum; nuclear@0: // Sum of vision latency times nuclear@0: //double VisionLagSum; nuclear@0: // Count of vision frames nuclear@0: int VisionFrames; nuclear@0: nuclear@0: // Statistics results: nuclear@0: nuclear@0: LocklessUpdater Results; nuclear@0: nuclear@0: void calculateResults(); nuclear@0: nuclear@0: OVR::ObserverScope calculateResultsSubject; nuclear@0: OVR::Lock calculateResultsLock; nuclear@0: nuclear@0: public: nuclear@0: LagStatsCalculator(); nuclear@0: nuclear@0: void GetLatestResults(LatencyStatisticsResults* results); nuclear@0: void AddResultsObserver(ObserverScope *calculateResultsObserver); nuclear@0: nuclear@0: public: nuclear@0: // Internal instrumentation interface: nuclear@0: nuclear@0: // EndFrame() instrumentation nuclear@0: void InstrumentEndFrameStart(double timestamp); nuclear@0: void InstrumentEndFrameEnd(double timestamp); nuclear@0: nuclear@0: // DK2 latency tester instrumentation nuclear@0: // Note: This assumes that it is called right before InstrumentEndFrameEnd() nuclear@0: void InstrumentLatencyTimings(FrameTimeManager& ftm); nuclear@0: nuclear@0: // Eye pose instrumentation nuclear@0: void InstrumentEyePose(const ovrTrackingState& state); nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: }} // namespace OVR::CAPI nuclear@0: nuclear@0: #endif // OVR_CAPI_LatencyStatistics_h