-
Notifications
You must be signed in to change notification settings - Fork 1.1k
wgpu-core implementation for external textures #7823
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
base: trunk
Are you sure you want to change the base?
Conversation
Make wgsl-in correctly parse `texture_external` texture declarations, and allow such textures to be used in `textureDimensions()`, `textureSampleBaseClampToEdge()`, and `textureLoad()` function calls. In IR these are represented by the `ImageClass::External` image class, which is a 2D, non-multisampled, non-mipmapped, float-sampled image. Adds a new Capability `TEXTURE_EXTERNAL` and ensure validation rejects shaders containing external textures if this capability flag is not set. This capability is enabled for validation by wgpu devices which support the `TEXTURE_EXTERNAL` feature (currently only when using the noop backend), and by the Naga CLI when validating-only or when outputting WGSL. The WGSL backend can of course emit `ImageClass::External` images directly as `texture_external` textures. Other backends are, for now, unimplemented. Lastly, we add a snapshot test covering all the valid uses of a texture_external texture. These are: - As a global variable declaration - As an argument to the built-in functions `textureDimensions()`, `textureSampleBaseClampToEdge()`, and `textureLoad()` - As an argument to user-defined function declarations and calls. We keep these in their own test so that we can control which targets to run them against (currently WGSL and IR). When external textures are supported by all Naga backends we can, if so inclined, integrate these with existing texture tests.
1f52857
to
53866d8
Compare
`ExternalTexture` will form the basis of wgpu's implementation of WebGPU's `GPUExternalTexture`. [1] The application will be responsible for creating `Texture`(s) and `TextureView`(s) from the external texture source and managing their lifecycle. It may have a single RGBA texture, or it may have multiple textures for separate Y and Cb/Cr planes. It can then create an external texture by calling `create_external_texture()`, providing the texture views and a descriptor. The descriptor provides the following required information: * Whether the texture data is RGBA, or multiplanar or interleaved YCbCr. * The purpoted size of the external texture, which may not match the actual size of the underlying textures. * A matrix for converting from YCbCr to RGBA, if required. * A transform to apply to texture sample coordinates, allowing for rotation and crop rects. The external texture stores a reference to the provided texture views, and additionally owns a `Buffer`. This buffer holds data of the type `ExternalTextureParams`, and will be provided as a uniform buffer to shaders containing external textures. This contains information that will be required by the shaders to handle external textures correctly. Note that attempting to create an external texture will fail unless the `Feature::EXTERNAL_TEXTURE` feature is enabled, which as of yet is not supported by any HAL backends. Additionally add the relevant API to wgpu, implemented for the wgpu-core backend. The web and custom backends are unimplemented. [1] https://www.w3.org/TR/webgpu/#gpuexternaltexture
In upcoming patches, wgpu will allowing the creation of bind groups with either `TextureView`s or `ExternalTexture`s bound to a `BindingType::ExternalTexture` bind group layout entry. Wgpu-hal and the Naga-generated shaders must be able to handle both of these cases. For external textures they will be provided a uniform buffer containing the external texture's `ExternalTextureParams`. For the texture view case, we must therefore provide the same. To do this, we create a single buffer per device which can be shared between all texture views. We initialize it with the required values in Device::late_init_resources_with_queue(). We know that texture views must have a single RGBA plane, with no rotation or crop-rect. The only thing that can vary between them is their size. We will therefore use the value of [0, 0] in the params buffer to indicate to the shader that it should query the actual texture's size rather than using the value provided in the buffer.
Adds a `BindingResource` variant for external textures. In core's create_bind_group() implementation, allow binding either external textures or texture views to `BindingType::ExternalTexture` layout entries. In either case, provide HAL with a `hal::ExternalTextureBinding`, consisting of 3 `hal::TextureBinding`s and a `hal::BufferBinding`. In the texture view case we use the device's default params buffer for the buffer. When there are fewer than 3 planes we can simply repeat an existing plane multiple times - the contents of the params buffer will ensure the shader only accesses the correct number of planes anyway. Track the view or external texture in `BindGroupStates` to ensure they remain alive whilst required. And finally, add the corresponding API to wgpu, with an implementation for the wgpu-core backend.
Adds validation tests using the noop backend covering creation of external textures, and creation of bind groups containing external textures.
53866d8
to
ec8b51a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good overall!
/// Uniform buffer containing [`ExternalTextureParams`] with values such | ||
/// that a [`TextureView`] bound to a [`wgt::BindingType::ExternalTexture`] | ||
/// binding point will be rendered correctly. | ||
pub(crate) default_external_texture_params_buffer: std::sync::OnceLock<Arc<Buffer>>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately the device can't hold wgpu-core buffers since buffers hold a strong ref to devices. This should be a hal buffer, you can use zero_buffer
as inspiration.
Connections
Depends on #7822
Part of #4386
Description
Add wgpu and wgpu-core implementation for external texture. wgpu-hal and naga implementations to follow, so for now this isn't particularly useful. But it does work with the noop backend, as can be seen in the added validation tests
Testing
Noop backend validation tests. Local testing. CTS testing can follow when more pieces are in place.
Squash or Rebase?
Rebase. If there are
fixup!
commits after review then squash them into the appropriate commit firstChecklist
cargo fmt
.taplo format
.cargo clippy --tests
. If applicable, add:--target wasm32-unknown-unknown
cargo xtask test
to run tests.CHANGELOG.md
entry.Don't think this is changelog worthy yet