I’m not a computer expert, no take my comments with a salt. However, I have been plagued with the FPS blues in UE 5.4 so tried to work on the problem, if only so I could actually use UE again.
I seemed to me that there is actually two problems with FPS rolled into one. Firstly, the capping FPS to 60 frames, which means there is less frames to play with. Secondly, the frames are being used in part for UE5 to create shaders on the fly.
The first problem may not be the making of UE and a have a simple solution way be in Window 11. Mirosoft seems to be “greening” Window 11. If you look at the settings in “System > Power & Battery > Energy Recommendations” there is a option which says “Lower your refresh rate to 60 Hz to conserve energy”. Thiis may not have anything (and you may be right), but it seemed to me that it was a coincidence that iI was also getting 60 FPS on my screen. It made me see whether I could turn the 60 Hz off and see what happens. After so looking I found an option in “System > Display > Advanced display” which have the option to choose “Choose a refresh rate”. It had the rate from “60.03 Hz” tp “144.03 Hz”, so I chose the latter. When I went back to UE. The editor screen when to 120 FPS. This may be nuts, but give it a go and see what happens.
Now to the main problem and TLRD for those wanting the conclusion, the FPS may because the frames are now being used for creating shaders on the fly when running PIE, The journey for this started with a look at my output log. Here is an extract from my output log:
"Creating RTPSO with 18 shaders (0 cached, 18 new) took 166.35 ms. Compile time 43.76 ms, link time 122.57 ms.
…
LogD3D12RHI: Creating RTPSO with 17 shaders (0 cached, 17 new) took 47.95 ms. Compile time 37.30 ms, link time 10.63 ms.
…
Creating RTPSO with 18 shaders (10 cached, 8 new) took 47.75 ms. Compile time 39.12 ms, link time 8.61 ms.‘’
This told me that UE was creating the shaders around the time of the “drops” displayed in the FPS counter on the screen. This was a theory, but I needed to delve deeper to see whether “RTPSO” had any relevance. With some Google help I was able to find out that it was “ray tracing pipeline state object” or RTPSO for short.
My does RTPSO to get the data from frames on the fly to create shaders in DX12. I don’t say that I understand the computer program mumble, but in the " Ray Tracing Gems High-Quality and Real-Time Rendering with DXR and Other APIS" article by " Copyright © 2019 by NVIDIA". The author says that:
“Fortunately, both DirectX Raytracing and all other NVIDIA ray tracing APIs enabled by RTX expose the ability to compile in parallel multiple ray tracing shaders to machine code”.
The author then explains what this means in practical terms:
“This parallel compilation can take advantage of the multiple cores of today’s CPUs. In the
experimental UE4 implementation, we used this functionality by simply scheduling
separate tasks, each of which compiled a single ray tracing shader or hit group into
what DXR calls a collection. Every frame, if no other shader compilation tasks were
already executing, we checked if any new shaders were needed and not available.
If any such shaders were found, we started a new batch of shader compilation
tasks. Every frame we also checked if any prior set of shader compilation tasks
had completed. If so, we created a new RTPSO, replacing the previous one. At any
time, a single RTPSO is used for all DispatchRays() invocations in a frame. Any
old RTPSOs replaced by a new RTPSO are scheduled for deferred deletion when no
longer used by any in-flight frames. Objects for which a required shader was not yet
available in the current RTPSO were removed (skipped) when building the TLAS.”
The shaders are then held in the Shader Binding Table, which what stored in memory and eventualy stored in my project in the “DerivedDataCache” folder. The use of the table is then used to make the changes to the shader:
“This table is a memory buffer made up of multiple records, each containing an opaque shader identifier and some shader parameters that are equivalent to what DirectX 12 calls a root table (for a Graphics Pipeline Draw or Compute Pipeline Dispatch). Since this first experimental implementation was designed to update shader parameters for every object in the scene at every
frame, the Shader Binding Table management was simple, mimicking that of a
command buffer. The Shader Binding Table was allocated as an N-buffered linear
memory buffer, with size dictated by the number of objects in the scene. At every
frame we simply started writing the entire Shader Binding Table from scratch in
a GPU-visible CPU-writable buffer (in an upload heap).”
The author concluded that RTPSO is there to stay, but is somewhat expensive in some practical applications:
“The recent introduction of dedicated hardware for ray tracing acceleration and the
addition of ray tracing support in graphics APIs encouraged us to be innovative
and experiment with a new way of hybrid rendering, combining rasterization and
ray tracing. We went through the engineering practice of integrating ray tracing
in Unreal Engine 4, a commercial-grade game engine. We invented innovative
reconstruction filters for rendering stochastic effects such as glossy reflections, soft
shadows, ambient occlusion, and diffuse indirect illumination with as few as a single
path per pixel, making these expensive effects more practical for use in real time.
We have successfully used hybrid rendering to create two cinematic-quality demos.”
In with that I ended my journey more knowldge, but with the conclusion that my high FPS counter may be the books for history.