-
Notifications
You must be signed in to change notification settings - Fork 329
Open
Labels
Milestone
Description
There are a lot of possible semantics for importing canvases as GPUExternalTexture
s. This issue was first raised by @shaoboyan here: #1415 (comment). Yesterday I was trying to come up with a proposal, so I decided to write out the options.
First, we should talk about what the use cases are. This was discussed on VF2F day 3. Cases I'm aware of:
- Have some UI element or text that changes often (~every frame) and needs to be integrated into a 3D scene. For example, XR UI rendered with 2d canvas, or an FPS counter.
- Note, for UI/text that is rendered less frequently, it's probably better to copy into a non-external
GPUTexture
. One example is a label atlas for labels on a map/globe.
- Note, for UI/text that is rendered less frequently, it's probably better to copy into a non-external
- Interop between WebGL and WebGPU, primarily(?) for partially-ported applications (e.g. deep image processing pipelines).
- This can be done, with some overhead, with
copyExternalImageToTexture
.
- This can be done, with some overhead, with
The different canvas contexts behave in very different ways, and it's tricky to reconcile them. Here are some options, with caveats, which can be partially mixed and matched.
- Error/no-op.
- Make drawing to the imported canvas an error or no-op. Seems too intrusive on the 2d canvas and WebGL APIs.
- Clearing.
- For {2d, webgl with
preserveDrawingBuffer: true
} sources, importing clears the source drawing buffer. - 2a. Clear like
clearRect
ortransferToImageBitmap
.- For {webgl with
preserveDrawingBuffer: false
, webgpu} sources, I think this is the same thing that presenting does. (Takes the drawing buffer and leaves a new, blank one.)
- For {webgl with
- Note: 2d canvas contexts do not normally have such a semantic.
OffscreenCanvas.transferToImageBitmap
does this, but AFAIK canvas elements can only do this withclearRect
. Resizing a 2d canvas is not the same; it also clears persistent state likefillStyle
.- 2b. Clear like canvas resize.
- For {2d, webgl with
- Copy-on-write.
- For all canvas sources,
importExternalTexture
effectively makes a copy of the contents of the canvas. Implementations must implement copy-on-write to optimize. - Most obvious semantic for users. But harder for implementations.
- "Write" is well-defined in WebGL, but I'm not sure about 2d canvas since it doesn't have an equivalent of
preserveDrawingBuffer: false
. - For a WebGPU source canvas, we avoided defining "write" by saying "present iff you called
getCurrentTexture
", so either browsers would have to define it, or the spec would have to use option 2 for WebGPU canvases specifically.
- For all canvas sources,
- Restrict import canvas context types.
- At least for now, disallow importing from any (or all!) types of input canvases. Users would have to use
copyExternalImageToTexture
instead for certain canvas types. - It seems like a no-brainer to restrict imports to, at most, only
2d
/webgl
/webgl2
canvases.
- At least for now, disallow importing from any (or all!) types of input canvases. Users would have to use
- Restrict to
OffscreenCanvas
only. Requires browser to implementOffscreenCanvas
.- Allow importing
OffscreenCanvas
only, notHTMLCanvasElement
. Rely on the semantic oftransferToImageBitmap
to define what happens - conveniently, it is fundamentally similar, asImageBitmap
s are also immutable. - Most likely restrict to constructed
OffscreenCanvas
es only;OffscreenCanvas
es fromtransferControlToOffscreen()
are not important here. - Possible porting pain for apps previously that normally use HTMLCanvasElement for this.
- Allow importing
ImageBitmap
import instead of canvas import. Requires browser to implementOffscreenCanvas
andtransferToImageBitmap
.- Disallow importing from all input canvases, but add importing from
ImageBitmap
, which users would use with the actualtransferToImageBitmap()
method. Could, but would not have to, consume (close) the importedImageBitmap
.
- Disallow importing from all input canvases, but add importing from
- Make drawing to the imported canvas cause immediate destruction of the
GPUExternalTexture
.
Proposal
- 4: restrict to only
2d
/webgl
/webgl2
- plus
- 5: constructed
OffscreenCanvas
es only, rely on the semantic oftransferToImageBitmap
; - or: 2a, 2b, 3, 7
- 5: constructed
AshleyScirra