Bug 1645528 Comment 14 Edit History

Note: The actual edited comment in the bug view page will always show the original commenter’s name and original timestamp.

New information: It looks like on Windows, when the GPU process is used (so most of the time), vsync notifications to the compositor also have to roundtrip through the parent-process main thread. That's because they're delivered via PVsyncBridge which is a sub-protocol of PGPU, whose parent process endpoint lives on the main thread. So compositor vsync goes: vsync thread -> main thread -> GPU process compositor thread. This was surprising to me. It also means that, today, on Windows with GPU process, content process animations have the potential to stay fluid while the parent process main thread is blocked. But their result won't reach the screen, because the compositor thread only composites when it receives vsync. So, effectively, it behaves the same as your proposed patch.

Anyway, here's an idea I had before I found out the GPU process vsync situation:

One idea would be to make PVSync a sub-protocol of PCompositorBridge - the protocol that connects the compositor thread to the various main threads (both parent and content). At the moment, vsync notifications are sent to the compositor thread already. So, for the vsync notifications that are sent to the various main threads, we could send them from the compositor thread rather than via the background thread. In terms of thread hops, this would be:
 - Equivalent to what we do today on Android and macOS. Instead of vsync thread -> background thread -> content, we'd have vsync thread -> compositor thread -> content.
 - Strictly worse on Windows which has a GPU process (and the compositor thread lives in the GPU process), because the Windows vsync source lives in the parent process. So rather than vsync thread -> background thread -> content, we would now go vsync thread -> main thread thread (oops!!) -> compositor thread -> content. We might be able to move the vsync source into the GPU process, at which point this would again be equivalent.
 - Strictly worse on Linux compared to the proposed patch in this bug (which makes PVsync a sub-protocol of PBrowser).
 - Equivalent in a potential future world where macOS has a GPU process, because on macOS we can definitely put the vsync source into the GPU process.

But, other than the extra thread hops, it might be more efficient: PCompositorBridge already has infrastructure for connecting windows to browsers, or rather "compositors" to "LayersId", [without creating one protocol instantiation per browser](https://searchfox.org/mozilla-central/rev/a5d9abfda1e26b1207db9549549ab0bdd73f735d/gfx/layers/ipc/PCompositorBridge.ipdl#70-94):

```
[...] The
 *   CompositorBridgeChild is a singleton in the content process. Note that
 *   a given content process may have multiple browser instances (represented
 *   by BrowserChild instances), that are attached to different windows, and therefore
 *   rendered by different compositors. This means that when a browser instance
 *   sends messages via its CompositorBridgeChild, the corresponding
 *   ContentCompositorBridgeParent has to use the layers id in the message
 *   to find the correct compositor or CompositorBridgeParent to pass the message
 *   on to.
```

There's another advantage of sending vsync via the compositor thread, but it's rather orthogonal to this bug. I'll attempt to describe it anyway:
If we send vsync to content via the compositor, we could have some nice ordering guarantees. We could give the compositor a shot at handling vsync before the we forward vsync to the content process. And we could use this to sample compositor-side APZ scroll animations and forward the updated scroll position value to content processes, and make sure that this value arrives before the vsync notification arrives. As a result, the upcoming content paint would always take the new position into account.
But, as I said, that's a rather orthogonal issue. We could start out with having PVSync a sub-protocol of PBrowser and I could still try to move it to PCompositorBridge later.
New information: It looks like on Windows, when the GPU process is used (so most of the time), vsync notifications to the compositor also have to roundtrip through the parent-process main thread. That's because they're delivered via PVsyncBridge which is a sub-protocol of PGPU, whose parent process endpoint lives on the main thread. So compositor vsync goes: vsync thread -> main thread -> GPU process compositor thread. This was surprising to me. It also means that, today, on Windows with GPU process, content process animations have the potential to stay fluid while the parent process main thread is blocked. But their result won't reach the screen, because the compositor thread only composites when it receives vsync. So, effectively, it behaves the same as your proposed patch.

Anyway, here's an idea I had before I found out about the GPU process vsync situation:

One idea would be to make PVSync a sub-protocol of PCompositorBridge - the protocol that connects the compositor thread to the various main threads (both parent and content). At the moment, vsync notifications are sent to the compositor thread already. So, for the vsync notifications that are sent to the various main threads, we could send them from the compositor thread rather than via the background thread. In terms of thread hops, this would be:
 - Equivalent to what we do today on Android and macOS. Instead of vsync thread -> background thread -> content, we'd have vsync thread -> compositor thread -> content.
 - Strictly worse on Windows which has a GPU process (and the compositor thread lives in the GPU process), because the Windows vsync source lives in the parent process. So rather than vsync thread -> background thread -> content, we would now go vsync thread -> main thread thread (oops!!) -> compositor thread -> content. We might be able to move the vsync source into the GPU process, at which point this would again be equivalent.
 - Strictly worse on Linux compared to the proposed patch in this bug (which makes PVsync a sub-protocol of PBrowser).
 - Equivalent in a potential future world where macOS has a GPU process, because on macOS we can definitely put the vsync source into the GPU process.

But, other than the extra thread hops, it might be more efficient: PCompositorBridge already has infrastructure for connecting windows to browsers, or rather "compositors" to "LayersId", [without creating one protocol instantiation per browser](https://searchfox.org/mozilla-central/rev/a5d9abfda1e26b1207db9549549ab0bdd73f735d/gfx/layers/ipc/PCompositorBridge.ipdl#70-94):

```
[...] The
 *   CompositorBridgeChild is a singleton in the content process. Note that
 *   a given content process may have multiple browser instances (represented
 *   by BrowserChild instances), that are attached to different windows, and therefore
 *   rendered by different compositors. This means that when a browser instance
 *   sends messages via its CompositorBridgeChild, the corresponding
 *   ContentCompositorBridgeParent has to use the layers id in the message
 *   to find the correct compositor or CompositorBridgeParent to pass the message
 *   on to.
```

There's another advantage of sending vsync via the compositor thread, but it's rather orthogonal to this bug. I'll attempt to describe it anyway:
If we send vsync to content via the compositor, we could have some nice ordering guarantees. We could give the compositor a shot at handling vsync before the we forward vsync to the content process. And we could use this to sample compositor-side APZ scroll animations and forward the updated scroll position value to content processes, and make sure that this value arrives before the vsync notification arrives. As a result, the upcoming content paint would always take the new position into account.
But, as I said, that's a rather orthogonal issue. We could start out with having PVSync a sub-protocol of PBrowser and I could still try to move it to PCompositorBridge later.
~~New information: It looks like on Windows, when the GPU process is used (so most of the time), vsync notifications to the compositor also have to roundtrip through the parent-process main thread.~~ Nevermind, I was wrong about this. PVsyncBridge is a top-level protocol whose parent-side endpoint lives on the vsync thread.

One idea would be to make PVSync a sub-protocol of PCompositorBridge - the protocol that connects the compositor thread to the various main threads (both parent and content). At the moment, vsync notifications are sent to the compositor thread already. So, for the vsync notifications that are sent to the various main threads, we could send them from the compositor thread rather than via the background thread. In terms of thread hops, this would be:
 - Equivalent to what we do today on Android and macOS. Instead of vsync thread -> background thread -> content, we'd have vsync thread -> compositor thread -> content.
 - Similar on Windows with a GPU process, but with two instead of one process hops, since the Windows vsync source lives in the parent process. So rather than vsync thread (parent) -> background thread (parent) -> content, we would now go vsync thread (parent) -> compositor thread (gpu) -> content. We might be able to move the vsync source into the GPU process, which would eliminate the extra process hop.
 - Strictly worse on Linux compared to the proposed patch in this bug (which makes PVsync a sub-protocol of PBrowser).
 - Equivalent in a potential future world where macOS has a GPU process, because on macOS we can definitely put the vsync source into the GPU process.

But, other than the extra thread hops, it might be more efficient: PCompositorBridge already has infrastructure for connecting windows to browsers, or rather "compositors" to "LayersId", [without creating one protocol instantiation per browser](https://searchfox.org/mozilla-central/rev/a5d9abfda1e26b1207db9549549ab0bdd73f735d/gfx/layers/ipc/PCompositorBridge.ipdl#70-94):

```
[...] The
 *   CompositorBridgeChild is a singleton in the content process. Note that
 *   a given content process may have multiple browser instances (represented
 *   by BrowserChild instances), that are attached to different windows, and therefore
 *   rendered by different compositors. This means that when a browser instance
 *   sends messages via its CompositorBridgeChild, the corresponding
 *   ContentCompositorBridgeParent has to use the layers id in the message
 *   to find the correct compositor or CompositorBridgeParent to pass the message
 *   on to.
```

There's another advantage of sending vsync via the compositor thread, but it's rather orthogonal to this bug. I'll attempt to describe it anyway:
If we send vsync to content via the compositor, we could have some nice ordering guarantees. We could give the compositor a shot at handling vsync before the we forward vsync to the content process. And we could use this to sample compositor-side APZ scroll animations and forward the updated scroll position value to content processes, and make sure that this value arrives before the vsync notification arrives. As a result, the upcoming content paint would always take the new position into account.
But, as I said, that's a rather orthogonal issue. We could start out with having PVSync a sub-protocol of PBrowser and I could still try to move it to PCompositorBridge later.

Back to Bug 1645528 Comment 14