FrameTimingManager.GetLatestTimings always returning 0 timings.

Hello,

I am trying to make use of the FrameTimingManager, but GetLatestTimings always seems to return 0 timings.

This is what I am currently doing while trying to see if it works:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;
using System.Text;

public class FrameTimeDisplay : MonoBehaviour
{
    public TMP_Text textElement = null;
    private FrameTiming[] m_frameTimings = new FrameTiming[8];
    private StringBuilder m_stringBuilder = new StringBuilder(32);

    private void Update()
    {
        uint capturedAmount = FrameTimingManager.GetLatestTimings(8, m_frameTimings);

        m_stringBuilder.Length = 0;
        if (capturedAmount > 0)
        {
            // Do some calculations here...
           
            // Debug display...
            m_stringBuilder.Append("CPU: ");
            m_stringBuilder.Append(m_frameTimings[0].cpuFrameTime);
            m_stringBuilder.Append("ms\n");
            m_stringBuilder.Append("GPU: ");
            m_stringBuilder.Append(m_frameTimings[0].gpuFrameTime);
            m_stringBuilder.Append("ms");
        }
        textElement.SetText(m_stringBuilder);

        FrameTimingManager.CaptureFrameTimings();
    }
}

The Unity version I am using is 2018.1.4f1. Windows editor & standalone.
Am I doing something wrong here or does my system not support it?

This post from Nov 2017 shows the correct usage:

But it also reads:
“It is also launching just on Xbox One but other platform support is coming soon.”

You already know what “soon” means in Unity jargon…

3 Likes

Actually, while this posting has a nice explanation, which is also much more helpful than the API documentation of those methods (thank you @timothyh_unity ), it’s not quite clear to me how exactly this works. Examples in the documentation would really help - and also, a clear statement on which platforms this can be used on now.

I tried code similar to what @Q-Ted posted, assuming that when I call FrameTimingManager.CaptureFrameTimings() at the end of the Update-method, it should then have data until the next call into Update(). But in the documentation, it says only “complete frames” are captured, and that could mean that when I call it between two updates, if the GPU is still busy rendering and that would explain I’m never getting frame timings.

By now, I have tried a variety of different approaches, including calling it directly before GetLatestTimings(), and also calling CaptureFrameTimings() in one frame, then GetLatestTimings() the next, then Capture again and so forth.

It does kind of look like maybe, this is still only Xbox One … but if that really is the case, it should absolutely say so in the API documentation.

I’d love to get those CPU frame timings - but apparently, for now, it seems I’ll have to go with XRStats (which only tells me about GPU time).

Btw, I’m on 2018.3.0b12. I could move to 2019.1.0alpha if that would help (and when Visual Effects Graph will work there, too :wink: ).

1 Like

I am based on the examples provided on the official documentation.

The value of m_gpuFrameTime is still 0,and I am running under non-Editor

Can anyone give a use case? Thank you very much!

The same weird case. I call everything once per frame:
rameTimingManager.CaptureFrameTimings ();
// uint Returns the number of FrameTimings it actually was able to get
allowedFrameTimings = FrameTimingManager.GetLatestTimings ( kNumFrameTimings, frameTimings );
if (frameTimings.Length < kNumFrameTimings) {
Debug.LogFormat ( “Skipping frame {0}, didn’t get enough frame timings.”, m_frameCount );
return;
}
m_gpuFrameTime = (double)frameTimings[0].gpuFrameTime;
m_cpuFrameTime = (double)frameTimings[0].cpuFrameTime;

But everything is 0 on OSX Unity 2019.2.9f1 :confused:

Everything is 0 on 2019.2.19 and Unity 2020.1.0a22 too :expressionless:

It works on XBox One only.

Based on past experiences, “coming soon” in this context can be interpreted as ~5 years. I wouldn’t expect this to be available earlier than Unity 2022, and there’s a significant chance it won’t be ever implemented.

2 Likes

It should actually work on almost all platforms now (Feb. 2020) - but I’m getting 0 too no matter what I do. I can make it scale (if I change to DirectX 12 only), but I see no performance improvement (might be due to my particles is CPU bound) however, something is still wrong as I get 0 for both “gpuFrameTime” and “cpuFrameTime”.

https://docs.unity3d.com/Manual/DynamicResolution.html

“Unity supports dynamic resolution on Xbox One, PS4, Nintendo Switch, iOS , macOS and tvOS (Metal only), Android (Vulkan only), Windows Standalone and UWP (DirectX 12 only).”

As for what I understand from that page, “DynamicResolution” refers to DynamicallyScalable, allowDynamicResolution and ScalableBufferManager. That’s what works in most platforms. Only the included example makes use of FrameTimingManager, but that doesn’t make it part of the Dynamic Resolution feature itself.

From:
https://docs.unity3d.com/ScriptReference/FrameTimingManager.html

“If the platform does not support returning this value it will return 0.”

I see what you mean, but it’s a pretty shitty move Unity to write all these systems are supported and then on the same page provide a code sample that only works on Xbox One :smile:

When that said (and I already wrote that feedback to Unity) that code sample doesn’t do as it indicates. “DetermineResolution()” does not at all “determine” any resolution…it writes a Debug.Log…that’s it. And on that note, even when my frame froze for seconds, that Debug.Log wasn’t fired, so that part doesn’t work either.
Anyway, even if it worked the code doesn’t do what it indicates with that method name.

And in relation to:
“If the platform does not support returning this value it will return 0.”

It would be nice with some indication of what “platforms wasn’t supported”. When they put it like that, it’s the same as saying “If it works it works, if not, good luck!” :slight_smile:

2 Likes

Truly honestly, I wouldn’t be surprised. Unity is now so big and has so many teams scattered around so many departments, that (IMHO) is perfectly possible that the guy who wrote the example for the docs had no connection at all with the guy/team developing the FrameTimeManager class. Or even if he had so, he may have been told the same “more platforms coming soon” reply.

I wouldn’t be surprised either! xD

The documentation here is so bad that it made me log in and post a response :slight_smile:

The example doesn’t actually do anything–it just returns a log. Somewhat useful for trying to figure out how the API works, but confusing. Aaaaaand, I get 0 as well, with no sense on what / when this works. DynamicResolution works like a charm, but this frame timing idea (which would be really useful) doesn’t seem implemented?

Has anyone here managed to get this to work?

1 Like

Personally I don’t think this will be ever implemented further. It looks like this feature was abandoned years ago. I don’t think they will continue with this given the new APIs / RP / DOTS / etc stuff they’re focusing on. If all, they’ll deprecate it and tell they’re working in something else much better ™ that might land in preview-alpha-experimental at some time within the next two years ™.

1 Like

… and then be deprecated right before they actually get it into a state of being useful, replaced with something that does almost exactly the same but isn’t quite compatible with the previous approach. Rinse. Repeat.

Valve? Valve? CanIHazSource2PrettyPlease?

2 Likes

See here:
https://stackoverflow.com/questions/62531661/what-is-the-correct-usage-of-frametiming-and-frametimingmanager
FrameTimingManager is not supported for Windows. And looks like the smart programmers at Unity decided to just return 0 instead of printing a log message that it is not supported, throwing an exception, or at least documenting this fact at Unity - Scripting API: FrameTimingManager .

Quick and dirty solution which shows at least the FPS, updated once per second:

using UnityEngine;

public class FPS : MonoBehaviour
{
    private float _fpsUpdate;
    private float _lastFps;

    public void OnGUI()
    {
        _fpsUpdate += Time.deltaTime;
        if (_fpsUpdate > 1)
        {
            _lastFps = 1.0f / Time.deltaTime;
            _fpsUpdate = 0;
        }
        int w = Screen.width, h = Screen.height;
        GUIStyle style = new GUIStyle();
        Rect rect = new Rect(w / 10 * 9, 0, w / 10, h * 3 / 100);
        style.alignment = TextAnchor.UpperRight;
        style.fontSize = h * 3 / 100;
        style.normal.textColor = new Color(1.0f, 1.0f, 1.0f, 1.0f);
        GUI.backgroundColor = Color.black;
        string text = string.Format("{0:0.} fps", _lastFps);
        GUI.Box(rect, text);
    }
}

Just drop the script on an empty GameObject. Looks like this:


But would be much better to have the exact numbers for the GPU and CPU times., as the Stats window in the editor can do it.

Tbh, while useful in general, an FPS-counter is nothing like getting info on how much time is spent on the GPU / CPU.

For VR (where this is extremely important), you can at least use XRStats.TryGetGPUTimeLastFrame(…) to get the GPU frame time. Unfortunately, there is no equivalent for measuring the CPU time, so this is really only helpful if you’re GPU bound (on the other hand, being GPU can often be handled by simply reducing the render resolution - with CPU issues, there’s nothing that straightforward).

I actually don’t mind them returning 0: Getting exceptions for something like tracking performance statistics that could pop up depending on where the game is installed sounds like a recipe for disaster. Here’s some code I use with the XRStats fallback (this will only work for VR projects, and only on certain VR SDKs, and consider is “pseudocode” because it refers to other stuff in my performance tracking class - but it should get you started):

    private void CalculateFrameTimes() {
        uint frameCount = FrameTimingManager.GetLatestTimings((uint)frameTimings.Length, frameTimings);
        if (frameCount < 1) {
            CalculateFrameTimesXRStats();
        } else {
            ProcessFrameTimeGpu(frameTimings[0].gpuFrameTime);
            ProcessFrameTimeCpu(frameTimings[0].cpuFrameTime);
        }

        totalFrameTimeGpu += lastFrameTimeGpu;
        totalFrameTimeCpu += lastFrameTimeCpu;
      
        FrameTimingManager.CaptureFrameTimings();
    }

    private void CalculateFrameTimesXRStats() {
        if (XRStats.TryGetGPUTimeLastFrame(out float lastFrameTime)) {
            ProcessFrameTimeGpu(lastFrameTime);
        }
    }

The methods ProcessFrameTimeGpu() and ProcessFrameTimeCpu() do stuff like calculating the min/max, count frames over certain thresholds and so forth. Obviously, totalFrameTimeGpu and totalFrameTimeCpu are used to calculate the average frame times.

OpenVR has a method [IVRCompositor::GetFrameTiming](https://github.com/ValveSoftware/openvr/wiki/IVRCompositor::GetFrameTiming) which delivers a lot of useful data in Compositor_FrameTiming. This is used for adaptive quality in [ValveCamera](https://github.com/ValveSoftware/the_lab_renderer/blob/ae64c48a8ccbe5406aba1e39b160d4f2f7156c2c/Assets/TheLabRenderer/Scripts/ValveCamera.cs), which was part of Valve’s The Lab Renderer.

2 Likes

So, this is unity. Fool developers every now and then.
A simple interface to access cpu & gpu time would be great help for mobile game developers, but they would not offer it.

1 Like

How does FrameTimingManager.getLatestTimings(…), not work on the Windows platform? It makes zero f*****g sense. At the very least, it should work from within the Unity Editor, because that’s the one thing that is going to get used by all Unity developers. That one tool that all Unity developers use, and Unity didn’t think, “We should make it work on that one thing that all of our clients use; you know that one tool that the company is named after.”!

Maybe my reaction is a bit extreme–I just spent the last three hours adding code that is supposed to record the gpu frame render times in an automated data capture project, only to find out that the API I built said code on doesn’t f*****g work when you run it on a Windows Machine. I would have understood if it didn’t work on certain mobile devices, but this should work on anything and everything that Unity’s Profiler tool works on. There’s no f****g way that Unity can say they can’t grab said information when their own Profiler tool is able to grab said information.

Anyways, I’m going to have to find a different way to get this data because I really don’t want to tell my client, “Learn to use the Unity Profiler.”.

3 Likes

I understand the frustrations but I’d still prefer if we could keep the forums in a more even keeled and professional tone.

There are several long and complicated responses to why this is the current status of it but the short of it is: GPU profiling support is rather spotty right now and we’re actively working on fixing that. This is happening with a focus on getting GPU timings to the Profiler’s Recorder and ProfilerRecorder APIs as well as FrameTimingManager first, and then into the Profiler UI. Btw, as of 2020.1 Recorder can already get you GPU timings where the profiler UI can too, but only on Development builds. The newer ProfilerRecorder API allows us to also expose some of the stats in Release.

1 Like

Also, we are looking at updating the docs to be clearer about what is supported and what isn’t but given the upcoming holiday season, getting all the details for that is going a bit slower than ideal and we’ll likely not have an update before January.

2 Likes