Skip to content

Commit 4aa7e32

Browse files
authored
Explainer: Swap Chain (#1618)
* Explainer: Swap Chain * decoupling * zero or more
1 parent bb938b3 commit 4aa7e32

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

explainer/index.bs

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -796,6 +796,87 @@ Some alternatives are mentioned in issue [#747](https://github.com/gpuweb/gpuweb
796796

797797
## Canvas Output ## {#canvas-output}
798798

799+
Historically, drawing APIs (2d canvas, WebGL) are initialized from canvases using `getContext()`.
800+
However, WebGPU is more than a drawing API, and many applications do not need a canvas.
801+
WebGPU is initialized without a canvas - see [[#initialization]].
802+
803+
Following this, WebGPU has no "default" drawing buffer.
804+
Instead, a WebGPU device may be connected to *any number* of canvases (zero or more)
805+
and render to any number of them each frame.
806+
807+
Canvas context creation and WebGPU device creation are decoupled.
808+
Any `GPUCanvasContext` may be dynamically used with any `GPUDevice`.
809+
This makes device switches easy (e.g. after recovering from a device loss).
810+
(In comparison, WebGL context restoration is done on the same `WebGLRenderingContext` object,
811+
even though context state does not persist across loss/restoration.)
812+
813+
In order to access a canvas, an app gets a `GPUTexture` from the `GPUCanvasContext`
814+
and then writes to it, as it would with a normal `GPUTexture`.
815+
816+
### Swap Chains ### {#canvas-output-swap-chains}
817+
818+
Canvas `GPUTexture`s are vended in a very structured way:
819+
820+
- `canvas.getContext('gpupresent')` provides a `GPUCanvasContext`.
821+
- `GPUCanvasContext.configureSwapChain({ device, format, usage })` provides a `GPUSwapChain`,
822+
invalidating any previous swapchains, attaching the canvas to the provided device, and
823+
setting the `GPUTextureFormat` and `GPUTextureUsage` for vended textures.
824+
- `GPUSwapChain.getCurrentTexture()` provides a `GPUTexture`.
825+
826+
This structure provides maximal compatibility with optimized paths in native graphics APIs.
827+
In these, typically, a platform-specific "surface" object can produce an API object called a
828+
"swap chain" which provides, possibly up-front, a possibly-fixed list of 1-3 textures to render
829+
into.
830+
831+
### Current Texture ### {#canvas-output-current-texture}
832+
833+
A `GPUSwapChain` provides a "current texture" via `getCurrentTexture()`.
834+
For <{canvas}> elements, this returns a texture for the *current frame*:
835+
836+
- On `getCurrentTexture()`, `[[currentTexture]]` is created if it doesn't exist, then returned.
837+
- During the "[=Update the rendering=]" step, the browser compositor takes ownership of the
838+
`[[currentTexture]]` for display, and that internal slot is cleared for the next frame.
839+
840+
### `getSwapChainPreferredFormat()` ### {#canvas-output-preferred-format}
841+
842+
Due to framebuffer hardware differences, different devices have different preferred byte layouts
843+
for display surfaces.
844+
Any allowed format is allowed on all systems, but applications may save power by using the
845+
preferred format.
846+
The exact format cannot be hidden, because the format is observable - e.g.,
847+
in the behavior of a `copyBufferToTexture` call and in compatibility rules with render pipelines
848+
(which specify a format, see `GPUColorTargetState.format`).
849+
850+
Desktop-lineage hardware usually prefers `bgra8unorm` (4 bytes in BGRA order),
851+
while mobile-lineage hardware usually prefers `rgba8unorm` (4 bytes in RGBA order).
852+
853+
For high-bit-depth, different systems may also prefer different formats,
854+
like `rgba16float` or `rgb10a2unorm`.
855+
856+
### Multiple Displays ### {#canvas-output-multiple-displays}
857+
858+
Some systems have multiple displays with different capabilities (e.g. HDR vs non-HDR).
859+
Browser windows can be moved between these displays.
860+
861+
As today with WebGL, user agents can make their own decisions about how to expose these
862+
capabilities, e.g. choosing the capabilities of the initial, primary, or most-capable display.
863+
864+
In the future, an event might be provided that allows applications to detect when a canvas moves
865+
to a display with different properties so they can call `getSwapChainPreferredFormat()` and
866+
`configureSwapChain()` again.
867+
868+
#### Multiple Adapters #### {#canvas-output-multiple-adapters}
869+
870+
Some systems have multiple displays connected to different hardware adapters; for example,
871+
laptops with switchable graphics might have the internal display connected to the integrated GPU
872+
and the HDMI port connected to the discrete GPU.
873+
874+
This can incur overhead, as rendering on one adapter and displaying on another typically incurs
875+
a copy or direct-memory-access (DMA) over a PCI bus.
876+
877+
Currently, WebGPU does not provide a way to detect which adapter is optimal for a given display.
878+
In the future, applications may be able to detect this, and receive events when this changes.
879+
799880

800881
## Bitflags ## {#bitflags}
801882

0 commit comments

Comments
 (0)