Skip to content

Metal / MSL external texture implementation #8117

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: trunk
Choose a base branch
from

Conversation

jamienicol
Copy link
Contributor

Connections
Part of #4386

Description
Metal / MSL implementation of external textures. Similar to HLSL and DX12 implementation in #7826 and #8037

The first commit is a refactoring to split Writer::write_wrapped_functions() in to a separate function for each expression type. This has no functional change, just splits an already large function into smaller chunks in preparation for even more expression types being wrapped.

The second commit makes the external texture snapshot test slightly more interesting.

The third commit contains the MSL changes. These are basically exactly the same as the HLSL equivalent, the main difference being that MSL actually allows us to wrap textures in structs, meaning we are able to declare a type NagaExternalTextureWrapper which contains fields for each texture plane and the params buffer. We construct an instance of this for each global external texture passed into the entry point, and are then able to pass it around as a single parameter rather than having to pass each plane and the params struct separately.

The last commit contains the Metal HAL changes. We just need to create a resource binding for each plane and the params buffer. We also need to ensure that the parameters buffer's size matches the type of the MSL struct it is bound to, otherwise metal complains.

Testing
Covered by existing Naga snapshot and gpu tests

Squash or Rebase?

Rebase. I'll add fixup commits if required during review, then will manually squash these as appropriate prior to merging

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy --tests. If applicable, add:
    • --target wasm32-unknown-unknown
  • Run cargo xtask test to run tests.
  • If this contains user-facing changes, add a CHANGELOG.md entry.

@jamienicol jamienicol requested a review from a team as a code owner August 18, 2025 10:58
It was getting unwieldy, and upcoming commits are going to add
additional functions that will be wrapped.
…th vec2<i32> and vec2<i32> coordinates

The HLSL external texture implementation didn't have to do anything in
particular to handle both coordinate types, as int2 automatically gets
promoted to uint2. But in MSL this is not the case, and it is
therefore important to test that we correctly handle both coordinate
types.
This adds MSL backend support for `ImageClass::External`. (ie WGSL's
`external_texture` texture type). This is implemented very similarily
to the HLSL implementation in gfx-rs#7826.

Each external texture global variable is lowered to 3 `texture2d`s and
a buffer of type NagaExternalTextureParams. As usual in Naga's MSL
backend, these are passed as arguments to the entry point. The
bindings for each of these arguments are provided via the usual
binding map, using a new `BindExternalTextureTarget` variant of
`BindTarget`.

Unlike HLSL, MSL allows textures to be used as fields in structs. We
therefore immediately wrap these variables in a
`NagaExternalTextureWrapper` struct. This wrapper can then
conveniently be passed to either user-defined functions or builtin
implementations that accept an external texture.

The WGSL builtins `textureDimensions()`, `textureLoad()`, and
`textureSampleBaseClampToEdge()` are implemented using wrapper
functions using the regular `write_wrapped_functions()` machinery.
This contains the Metal HAL changes required to support external
textures. When creating a bind group we create resource bindings for
each of the 3 textures and parameters buffer that the external texture
has been lowered to. When creating the pipeline layout we fill the
`BindTarget` accordingly, so that the Naga MSL backend can bind each
of the global variables to which the the external texture has been
lowered to each of these resources.

We must also ensure the size of the buffer bound to the parameters
global matches the size of the MSL type, else metal validation
complains. We do this by adding a padding field to the rust-side
ExternalTextureParams struct, the size of which is used as the size of
the buffer to allocate.

Lastly we enable `Features::EXTERNAL_TEXTURE` on the Metal backend.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants