I am almost sure swapchain Present works without this Commit().
Looks like you're right. Commit() should only be called when modifying the visual tree, not after every frame.
From https://learn.microsoft.com/en-us/windows/win32/directcomp/architecture-and-...
The requirement to call Commit is similar to the concept of a "frame" except that, because the composition engine runs asynchronously, it can present several different frames between calls to Commit. In DirectComposition, a frame is a single iteration of the composition engine, and the interval spent by an application between two calls to Commit is called a batch.
There is a dedicated thread for composition, which I didn't implement. So I think now there must be a thread that waits for a vertical blank, then does a composition, and finally present the composition content to the screen.
I will refine my Commit() patches. The DXGI changes should be good.