1) We wanted to omit the unnecessary details from you to not be confusing and focus on the frequent frame repeat issue which seems to be hardware-agnostic, but feel the need now to elaborate in order to not give the impression that this is purely for research purposes and does not have a specific real-life application:
The real code is for a custom SteamVR headset runtime. However, frame repeating seems to be apparent and frequent also with reglar 3d programs/games on regular 120-240Hz monitors connected to gaming laptops (these models tested: Asus G752VS, HP Victus 15, Aorus 15G-XC). So reducing or eliminating frame repeating serves real life purpose, it’s not for academic research.
We’ve also been discussing this with an open-source game engine developer (Panda3D), since the issue exists also on there, not just pure Vulcan/DirectX.
So we believe getting to the bottom of this will be beneficial to 3d and engine devs and is not some fringe use case.
Regarding the VR headset runtime, it does not render game frames, it takes frames provided by any SteamVR game and just post-processes them to be usable for a VR displays and optics. This includes reusing previous frames if the game failed to render new frames on time, or doing more advanced things like reprojection and lens distortion correction.
The test program provided is meant to illustrate, that even when nothing of the sorts is done and just a blank frame is presented each frame, there’s still an alarming number of repeated frames at the monitor (every 30 seconds or so) with these laptops even at 120Hz. Here’s the laptop logs, together with a spreadhseet of the results: Program result logs on 3 laptops, Dec 13 2023.7z - pCloud
Blue-red alternating colors is just for the test and is a good way to visually notice the issue clearly as it happens and in a video camera capture. They are easier to spot during testing than stutters, although stutters are still visible themselves.
Since your hardware seems too powerful to reproduce the issue, here’s some CGI videos we created to show the kind of stuttering that will happen with real life use cases. There’s videos made to play on a 120Hz, 144Hz, 180Hz and 240Hz monitors. The simulated frame repeat is exactly at the middle of the video.
frame-long repeat: normal monitor - pCloud
(view the refresh rate video matching your monitor’s, in fullscreen)
And here’s video camera captures of the test program on our devices. recordings Dec 8 2023 - pCloud (recorded with two cameras simultaneously, one 120fps and one 480fps, logs text files show the offending frame indexes)
Here’s few GIF animations we’ve generated from the videos, of just the few frames where the frame repeat happens. gifs of the artifacts (slow mo) - pCloud
To summarize what the test program does:
2 grids have a white card moving each frame, mouse cursor is also moved each frame, top grid card and the mouse cursor, unlike the bottom grid card, compensate for the repeated frame as soon as the program becomes aware that it has occurred.
When a frame repeat happens, you notice both the white cards and mouse cursors freezing in place, then:
-
The mouse cursor jumps a position to compensate for the repeat.
-
The top card moves a cell, only later jumps a cell to compensate. This is because the next frame was already presented and the 3d program couldn’t recall the next presented frame when it learned that the current presented frame had been repeated.
-
The bottom white card just resumes as usual after the frame repeat, as it has not been programmed to compensate its position due to a frame repeat.
I’m sure you’ll agree that it’s not okay for the end user to experience this every 30 seconds or so on modern gaming laptops and at as low as 120Hz.
2) We are simultaneously testing the code using the VRWorks API, which is meant for VR and in theory should bypass DWM. We experience the issue with and without using VRWorks. Since VRWorks API needs an edit to the Windows registry to work with normal monitors, we are only supplying the pure DirectX version of the program to you for testing.
3) To clarify, the issue is not merely that only one frame sometimes stays longer / is displayed twice on the monitor than it should. There’s actually 2 mis-timed frames when this happens. The first frame gets repeated on the monitor, while the 2nd frame is already rendered and presented to the GPU and is displayed at the time slot of the 3rd expected frame (counted as 3rd if no repeating were to occur).
And often times, the frame is actually repeated twice or more in sequence, not just once.
4) SetFullscreenState does not seem to prevent the issue from happening. If there’s an alternative way to enable true fullscreen (I think you’re saying that what we do now is “only “windowed” fullscreen”?), please let us know.
5) Going one step ahead: is there any way to query the GPU or some other way determine a frame repeat is happening, before the repeating finishes? Is there any way to recall a presented frame or some other way halt the streaming of frames to the monitor when a frame is repeated once but hasn’t started streaming the next presented frame yet? This will at least solve the issue of frames repeated more than once and prevent later presented frames from being displayed later in time than they should have.