SetMaxFPS doesn't work on MSI Claw A1M

The GOALS game is clamping FPS to run on 60 FPS in the menu via SetMaxFPS.

However on a MSI Claw-A1MX (https://www.msi.com/Handheld/Claw\-A1MX/Specification) it doesn’t work as expected and seems to run with unbounded FPS evec though t.MaxFPS says 60 Stat FPS says higher numbers.

Attaching video of this

Steps to Reproduce

  1. Start GOALS game test config on MSI Claw (handheld)
  2. Open console and type stat FPS
  3. Open console and type t.MaxFPS
  4. see that the Max FPS says 60 while Stat FPS is indicating running above 60

Hi there,

Can you confirm that both bSmoothFrameRate and bUseFixedFrameRate are set to false? It is worth checking in the project settings, and in the relevant device profile.

There is also a possibility that the setting is getting superseded by GameUserSettings, which you can confirm by breakpointing in UEngine::SetMaxFPS which sets the cvar to see what it is being set to.

Thanks.

Hi Hayden

I’ll need to setup a remote debug session on the MSI to fully confirm this, but just looking at the code and ini files we never set bSmoothFrameRate nor bUseFixedFrameRate to true.

As I have debugged this on other platforms (Win64 PCs and other Win64 Handhelds like the Lenovo Legion Go (AMD based HW)), they don’t get this issue and I have placed breakpoints at SetMaxFPS in order to see who could set the FPS to something else. But nothing sticks out.

However as you saw in the video, SetMaxFPS is set to 60 which is what t.maxFPS is showing. But the FPS is above in 70+ FPS. Seems like SetMaxFPS isn’t doing anything on this specific HW.

It looks like from the recording that t.MaxFPS was looked up in the console but not set, since it suggest it was last set by scalability. Would you be able to set t.MaxFPS first to 120, then to 60, both via the console?

Setting by the console will have a higher priority than by scalability, so this will help rule out things being stomped elsewhere. Setting to 120 first might also be necessary since it is already reporting 60, so going to 120 then to 60 will avoid any issues with it not setting it due to not being a new value. 120Hz is also the maximum refresh rate of the device, so this should be “valid”.

I’m also curious to know what kind of 5.5 engine build you are using. Is this a source build maintained by your team or an external team? It’s not out of the realm of possibility that there is some code tying max FPS to battery or temperature level, for instance.

Regarding the 5.5 build - Changelist from Epic 5.5 stream is 40765517

Sorry for the slow replies was on a vacation over the long weekend.

I have now verified that the code in the Menu State actually does what it should do and sets the MaxFPS as it should, 60 FPS in highend, 30 FPS in Lowend. Managed to setup remote debugging on the MSI Claw, so I could properly debug it.

While debugging I found that the code that looks to handle the Clamping of FPS is void UEngine::UpdateTimeAndHandleMaxTickRate()

But the code here is kinda complex so I don’t really get how it works.

But from what I can tell bool FXeLLMaxTickRateHandler::HandleMaxTickRate(float DesiredMaxTickRate) is called and returns true and runs

xell_result_t ret = xellSleep(XeLLContext, GFrameCounter);

But the bEnabled flag is not set in the MSI case, so the code doesn’t take DesiredMaxTickRate into consideration. From what I can tell this can be the cause why it doesn’t clamp the FPS.

Thanks :slight_smile:

Yeah, I already reached out to the Intel dev rel people and showed the code in more detail that doesn’t work in XeLL.

I actually added r.XeLL.DisableTickRateHandler 1 in Engine.ini and that fixed the problem. So problem is solved :slight_smile: Thanks for the support.

Will look into this to see if setting t.maxFPS to 120 and then to 60 will give any different result.

By the way is there a way to get GetSupportedRefreshRates in Unreal, I saw that there is support on Android for this but doesn’t look like there is support in Win64. My thinking was if this is a intel Arc driver issue that it can only set MaxFPS to a supported refreshrate.

I’ll ask the infra team what exact P4 CL version of 5.5 that was integrated into our code. But we have a source build and we maintain this ourselves.

Sounds good, let me know how you get on with setting t.MaxFPS in the console.

Regarding getting refresh rates, you have a couple of options:

RHIGetAvailableResolutions gets all available resolutions and refresh rates for the monitor in use, including any above the currently set Window’s refresh rate. It also reports the NTSC broadcast rates, such as 29.97, 59.94, and 119.88.

There’s also the FPlatformMisc::GetMaxRefreshRate() that asks for the monitor’s configured maximum. From there, you can compute the VSync internals by incremental divisors, i.e., for a display currently set to 120Hz in Windows the first is /1 for 120Hz, then /2 for 60Hz, then /3 for 40Hz, etc.

Not a problem, I hope you enjoyed your vacation!

Are your other (non-problematic) platforms using non-Intel GPUs? The XeLL classes/functions you are referencing are part of the third party Intel XeSS plugin. Strictly speaking, you should approach the plugin developer (Intel in this case) for support for third party plugins, but I can provide some support based on a cursory look.

It looks as though there are a few situations where you can enter a code path where your desired tick rate isn’t utilised:

  1. When r.XeLL.MinIntervalUS is set to a value other than -1
  2. When r.XeLL.DisableTickRateHandler is set to 1
  3. When the XeLLMode flag is set to 0

As a next step I would see what these are set to in your project, and if necessary tweak them to observe if you can get the desired behaviour.

Fantastic, I’m glad to hear you were able to arrive at a solution.

I’ll go ahead and close this case now.