We’re seeing issues in long play sessions where the world time becomes large enough that we start running into floating point precision issues, specifically in materials on some platforms which do periodic motion based on View.Time. Also, things like UPrimitiveComponent::GetLastRenderTime() become imprecise since they use floats, not doubles even though UWorld::GetTimeSeconds() returns a double.
It seems like resetting the UWorld’s time periodically is not really viable since there are patterns like this in use in the Engine
Does Epic have any guidance here? It seems like View.Time could be a FLargeWorldRenderScalar, but then this also adds shader overhead. We could also wrap the time sent to the material, but then it doesn’t match the world time. Other than restarting the map, which isn’t transparent to the player, is there another approach that maybe we’re missing here?
About how long are these long play sessions? We don’t typically have session that last 24hrs+ which I’m imagining is about when you start seeing these kinds of issues. The Time Material node has a Period parameter you can use in some cases to avoid precisions issues caused by doing math that produces large numbers in a Material, but the truncation of world time from double to float will eventually getcha.
I’m reaching out internally to see what other alternatives are typically used for these situations, but several folks are out till next week.
It depends on the platform, there is a specific restricted platform which aggressively applies -ffast-math in shaders and it reproduces the issue in only an hour or so, which is only 3600 seconds, so possibly this a specific issue with the trig functions on that platform.
Not sure if we’re thinking of the same platform and this doesn’t affect the shader compiler, but we did recently submit CL 52229427 on //UE5/Main after a bit of performance testing ([related [Content removed]
I think it’s very reasonable to expect play sessions of hours, and ideally we’d have no issues like this over any period of time - but do you think your sessions may extend beyond 24hrs?
We are seeing other shader issues due that beyond Time uses that go away when disabling fast math, such as corruption/NaNs in materials computing tangent basis.
Sorry, I’m just re-reading this and wanted to confirm if this means when you disable fast math you no longer see animation and corruption/NaN issues, or if you still see the corruption/NaNs even with fast math disabled.
In my search so far, I haven’t found any known issues or workarounds with time float precision aside from in Niagara, but that work hasn’t been prioritized. In session-based games, when the server calls ServerTravel() with seamless travel disabled UWorld time gets reset in UWorld::InitializeActorsForPlay.
One consideration is that View.GameTime doesn’t accumulate when paused - you could potentially use an auto-pause screen if the user goes afk for a long enough. I’ve got a few more folks I want to follow up with and a bit more searching, but we may need to create a new issue for this.
This platform’s aggressive fastmath on the GPU (and prior to the change you mentioned, also CPU) which results in issues specific to that platform.
Would you mind creating a private EPS describing the changes you made to implement this? I think it might be something we’d like to implement also - I had created an internal issue with some suggestions however it only addressed the CPU changes and not GPU.
GameTime never wrapping around and being converted down to float from double for the renderer.
It depends on the platform, there is a specific restricted platform which aggressively applies -ffast-math in shaders and it reproduces the issue in only an hour or so, which is only 3600 seconds, so possibly this a specific issue with the trig functions on that platform. The period mode unfortunately doesn’t work here since the period in this specific material is not constant, it varies per instance.
This triggered a discussion internally about other systems that might encounter issues like this, which is why we wanted to ask Epic about this more generally. It seems like, unless you travel to another map, you could idle forever and eventually cause issues if there is no way of wrapping time around or time rebasing or something like that. Different systems would start to fail at different times, but eventually things would start to break, for example animation LOD which depends on GetLastRenderTime()
It is indeed that platform, thanks for the pointer to that CL. We are seeing other shader issues due that beyond Time uses that go away when disabling fast math, such as corruption/NaNs in materials computing tangent basis, which are hard to debug since they don’t occur in editor. Unfortunately, CFLAG_NoFastMath is also not hooked up on that platform.
but do you think your sessions may extend beyond 24hrs?
I don’t think so, but there is nothing preventing a player from idling in non-combat area indefinitely. We were wondering if there was some engine-level solution here to reset time semi-transparently to the player (ie a tiny pop would be fine), or if we basically need to do a hard map reload periodically (ie 12+ hrs) to reset the game time which would require more UX around it and possibly a special save game path.
Sorry, I’m just re-reading this and wanted to confirm if this means when you disable fast math you no longer see animation and corruption/NaN issues, or if you still see the corruption/NaNs even with fast math disabled.
Yes, disabling fastmath for the shaders via the non-default shader compiler flag resolves many of these issues, at least it lasts longer. The time issue happens much sooner on this platform than others (like 1hr vs many hours) and we also have other issues with materials which do things like derive tangent basis giving wildly different results on this platform.
This platform also has a platform-specific keyword similar to HLSL’s precise keyword and using that around these problematic expressions also prevents the issue, however this requires hand-editing the generated material HLSL.
I think there are two issues here really:
This platform’s aggressive fastmath on the GPU (and prior to the change you mentioned, also CPU) which results in issues specific to that platform.
GameTime never wrapping around and being converted down to float from double for the renderer. This goes wrong much sooner on this platform due to 1, which is how we noticed it, but it would eventually break on all platforms I think.
Would you mind creating a private EPS describing the changes you made to implement this?
Sure, we actually don’t really have a systemic solution, but I created a thread in that platform’s group so we can continue the discussion more directly.