这是indexloc提供的服务,不要输入任何密码
Skip to content

rgba8unorm canvas textures and IOSurface #2535

@kainino0x

Description

@kainino0x

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 rgba8unorm for 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).

  1. 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
  2. Implementations must either do an extra full-canvas blit, or have a path that doesn't use IOSurface (probably not possible in Chromium)
  3. 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions