-
Notifications
You must be signed in to change notification settings - Fork 345
Description
On macOS, Chromium (at least) backs all canvas textures with IOSurfaces. However, as I understand it, macOS IOSurfaces cannot be rgba8unorm, only bgra8unorm*. Our spec requires canvases can be configured as either rgba8unorm or bgra8unorm (Chromium currently only implements bgra8unorm).
* bgra8unorm IOSurfaces can apparently be bound to either rgba8unorm or bgra8unorm MTLTextures - this does reinterpretation, not swizzling.
The most common case where people actually need rgba8unorm canvases is when they try to write to them as storage textures. On Metal, bgra8unorm can also be universally used as a storage format (and all other usages).
Our initial thought was that we would have to allocate an intermediate rgba8unorm texture and then issue a final blit into the IOSurface. This would be quite costly in general though.
I ended up hacking around a bit to see what could work, and experimentally it seems like we could transparently "emulate" rgba8unorm canvas textures by transparently backing them with bgra8unorm MTLTextures.
- On Metal, bgra8unorm can do everything that rgba8unorm can do (which is everything)
- MSL is agnostic to the component order (RGBA/BGRA) - storage textures use the term
rgba8unormfor both, and accesses are in rgba order (correctly swizzled depending on the underlying texture) - Render attachments are agnostic to the component order
The only exception I'm aware of is copies, which see the byte order, and are not agnostic to the component order (and don't obey Metal texture view swizzling either). This means copy commands into these "emulated" textures (using copyBufferToTexture, copyTextureToBuffer, [EDIT: copyTextureToTexture], writeTexture, and copyExternalImageToTexture in some cases) would have to be emulated as well, using a blit instead of a real copy.
So, the alternatives. These are mostly implementation choices but I think it's worth discussing here because they're not trivial and maybe there's a spec level solution (I'm not seeing one though).
- Spec disallows rgba8unorm (and therefore storage) for canvas textures (and add optional feature for bgra8unorm storage) - not good on devices that prefer RGBA
1b. Spec disallows rgba8unorm only on mac - obviously not good for portability - Implementations must either do an extra full-canvas blit, or have a path that doesn't use IOSurface (probably not possible in Chromium)
- Implementations emulate rgba8unorm canvases using bgra8unorm, always enable the RENDER_ATTACHMENT usage on canvases, and emulate copies using blits
3b. Spec disallows copies on rgba8unorm canvases - again bad on devices that prefer RGBA