[WebGPU] Support binding GPUExternalTexture via importExternalTexture - #9936
Open
AdrianEddy wants to merge 2 commits into
Open
[WebGPU] Support binding GPUExternalTexture via importExternalTexture#9936AdrianEddy wants to merge 2 commits into
AdrianEddy wants to merge 2 commits into
Conversation
Implements the `GPUExternalTexture` binding type on the WebGPU backend, which was previously `unimplemented!()`. `Device::import_external_texture` imports a `GPUExternalTexture` from a video source (an `HTMLVideoElement` or a WebCodecs `VideoFrame`) via `GPUDevice.importExternalTexture`. The browser performs the YCbCr->RGB conversion internally, so unlike the plane-based `create_external_texture` used by the native backends, no plane textures or conversion matrices are supplied; a `texture_external` binding can then sample the frame with no copy. - `WebExternalTexture` now holds the `GpuExternalTexture` handle. - The `BindingResource::ExternalTexture` bind-group arm sets the entry's resource to that handle. - `ExternalTexture::destroy()` and its `Drop` are no-ops: a `GPUExternalTexture` has no `destroy()` and expires automatically. - The plane-based `create_external_texture` stays unsupported on this backend, since the browser builds external textures from a video source, not planes. - `ExternalTextureSource` and `GpuExternalTexture` are re-exported under `wgpu::webgpu`.
AdrianEddy
force-pushed
the
webgpu-external-texture-binding
branch
from
July 23, 2026 16:04
335b0fb to
e723d5a
Compare
evilpie
reviewed
Jul 25, 2026
evilpie
reviewed
Jul 25, 2026
- Move `ExternalTextureSource` from beside `DropCallback` down next to `WebExternalTexture`, with the rest of the external-texture code. - Build the bind-group entry with the generated `GpuBindGroupEntry::new_with_gpu_external_texture` instead of hand-rolling an `Object` cast plus the two setters.
AdrianEddy
force-pushed
the
webgpu-external-texture-binding
branch
from
July 26, 2026 12:12
256a5c9 to
d6ba736
Compare
inner-daemons
suggested changes
Jul 27, 2026
inner-daemons
left a comment
Collaborator
There was a problem hiding this comment.
Overall LGTM, just a few notes. Also, is it feasible for this to be tested in CI?
| &self, | ||
| source: &webgpu::ExternalTextureSource, | ||
| ) -> ExternalTexture { | ||
| let inner = self.inner.as_webgpu().import_external_texture(source); |
Collaborator
There was a problem hiding this comment.
I feel like we might want this to return a result so that calling it from a non-webgpu backend doesn't panic.
| /// a no-op. | ||
| #[cfg(webgpu)] | ||
| #[must_use] | ||
| pub fn import_external_texture( |
Collaborator
There was a problem hiding this comment.
We also have create_external_texture, I think both of these warrant some documentation on how they differ and what their use case is.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Implements the
GPUExternalTexturebinding type on the WebGPU backend, which was previouslyunimplemented!().A new
Device::import_external_textureimports aGPUExternalTexturefrom a video source — anHTMLVideoElementor a WebCodecsVideoFrame— viaGPUDevice.importExternalTexture. The browser performs the YCbCr-to-RGB conversion internally, so unlike the plane-basedcreate_external_textureused by the native backends, no plane textures or conversion matrices are supplied. Atexture_externalbinding can then sample the frame with no copy.WebExternalTexturenow holds theGpuExternalTexturehandle.BindingResource::ExternalTexturebind-group arm sets the entry's resource to that handle.ExternalTexture::destroy()and itsDropare no-ops: aGPUExternalTexturehas nodestroy()and expires automatically (aVideoFramesource stays valid until closed; anHTMLVideoElementsource for the current task).Device::create_external_textureremains unsupported on this backend, since the browser builds external textures from a video source rather than plane textures.ExternalTextureSourceandGpuExternalTextureare re-exported underwgpu::webgpu.Testing
Built for
wasm32-unknown-unknownwith--features webgpu.Validated end-to-end in headless Chrome on both the SwiftShader CPU WebGPU adapter and Dawn on a discrete GPU: a WebCodecs
VideoFrameis imported viaDevice::import_external_texture, sampled through atexture_externalbinding in a render pass on the caller'sDevice, and read back. The result reproduces the source's YCbCr matrix + range conversion exactly and matches acopyExternalImageToTexturereference of the same frame bit-for-bit. No automated test is added here, since the current wasm test harness has no way to synthesize a video source.Squash or Rebase?
Squash
Checklist
wgpumay be affected behaviorally.CHANGELOG.mdentries for the user-facing effects of this change are present.