Skip to content

Commit 95a760b

Browse files
authored
Implement queue.copy_external_image_to_texture for WebGL2 and improve WebGPU Impl (#3288)
Co-authored-by: Teodor Tanasoaia <[email protected]> Closes #1888
1 parent 964c94a commit 95a760b

25 files changed

+1220
-63
lines changed

CHANGELOG.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,10 @@ Additionally `Surface::get_default_config` now returns an Option and returns Non
103103

104104
`Instance::create_surface()` now returns `Result<Surface, CreateSurfaceError>` instead of `Surface`. This allows an error to be returned instead of panicking if the given window is a HTML canvas and obtaining a WebGPU or WebGL 2 context fails. (No other platforms currently report any errors through this path.) By @kpreid in [#3052](https://github.com/gfx-rs/wgpu/pull/3052/)
105105

106+
#### `Queue::copy_external_image_to_texture` on WebAssembly
107+
108+
There's a new api `Queue::copy_external_image_to_texture` which allows you to create wgpu textures from various web image primitives. Specificically from HtmlVideoElement, HtmlCanvasElement, OffscreenCanvas, and ImageBitmap. This provides multiple low-copy ways of interacting with the browser. WebGL is also supported, though WebGL has some additional restrictions, represented by the UNRESTRICTED_EXTERNAL_IMAGE_COPIES downlevel flag. By @cwfitzgerald in [#3288](https://github.com/gfx-rs/wgpu/pull/3288)
109+
106110
#### Instance creation now takes `InstanceDescriptor` instead of `Backends`
107111

108112
`Instance::new()` and `hub::Global::new()` now take an `InstanceDescriptor` struct which cointains both the existing `Backends` selection as well as a new `Dx12Compiler` field for selecting which Dx12 shader compiler to use.
@@ -300,14 +304,12 @@ let texture = device.create_texture(&wgpu::TextureDescriptor {
300304

301305
- Don't use a pointer to a local copy of a `PhysicalDeviceDriverProperties` struct after it has gone out of scope. In fact, don't make a local copy at all. Introduce a helper function for building `CStr`s from C character arrays, and remove some `unsafe` blocks. By @jimblandy in [#3076](https://github.com/gfx-rs/wgpu/pull/3076).
302306

303-
304307
## wgpu-0.14.2 (2022-11-28)
305308

306309
### Bug Fixes
307310

308311
- Fix incorrect offset in `get_mapped_range` by @nical in [#3233](https://github.com/gfx-rs/wgpu/pull/3233)
309312

310-
311313
## wgpu-0.14.1 (2022-11-02)
312314

313315
### Bug Fixes

Cargo.lock

+46-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ env_logger = "0.9"
5757
futures-intrusive = "0.4"
5858
fxhash = "0.2.1"
5959
glam = "0.21.3"
60+
image = { version = "0.24", default-features = false, features = ["png"] }
6061
libloading = "0.7"
6162
libc = "0.2"
6263
log = "0.4"

wgpu-core/src/command/transfer.rs

+15-6
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use std::iter;
2424

2525
pub type ImageCopyBuffer = wgt::ImageCopyBuffer<BufferId>;
2626
pub type ImageCopyTexture = wgt::ImageCopyTexture<TextureId>;
27+
pub type ImageCopyTextureTagged = wgt::ImageCopyTextureTagged<TextureId>;
2728

2829
#[derive(Clone, Copy, Debug)]
2930
pub enum CopySide {
@@ -44,6 +45,8 @@ pub enum TransferError {
4445
MissingCopySrcUsageFlag,
4546
#[error("destination buffer/texture is missing the `COPY_DST` usage flag")]
4647
MissingCopyDstUsageFlag(Option<BufferId>, Option<TextureId>),
48+
#[error("destination texture is missing the `RENDER_ATTACHMENT` usage flag")]
49+
MissingRenderAttachmentUsageFlag(TextureId),
4750
#[error("copy of {start_offset}..{end_offset} would end up overrunning the bounds of the {side:?} buffer of size {buffer_size}")]
4851
BufferOverrun {
4952
start_offset: BufferAddress,
@@ -66,6 +69,8 @@ pub enum TransferError {
6669
},
6770
#[error("unable to select texture mip level {level} out of {total}")]
6871
InvalidTextureMipLevel { level: u32, total: u32 },
72+
#[error("texture dimension must be 2D when copying from an external texture")]
73+
InvalidDimensionExternal(TextureId),
6974
#[error("buffer offset {0} is not aligned to block size or `COPY_BUFFER_ALIGNMENT`")]
7075
UnalignedBufferOffset(BufferAddress),
7176
#[error("copy size {0} does not respect `COPY_BUFFER_ALIGNMENT`")]
@@ -102,6 +107,10 @@ pub enum TransferError {
102107
format: wgt::TextureFormat,
103108
aspect: wgt::TextureAspect,
104109
},
110+
#[error(
111+
"copying to textures with format {0:?} is forbidden when copying from external texture"
112+
)]
113+
ExternalCopyToForbiddenTextureFormat(wgt::TextureFormat),
105114
#[error("the entire texture must be copied when copying from depth texture")]
106115
InvalidDepthTextureExtent,
107116
#[error(
@@ -701,8 +710,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
701710
#[cfg(feature = "trace")]
702711
if let Some(ref mut list) = cmd_buf.commands {
703712
list.push(TraceCommand::CopyBufferToTexture {
704-
src: source.clone(),
705-
dst: destination.clone(),
713+
src: *source,
714+
dst: *destination,
706715
size: *copy_size,
707716
});
708717
}
@@ -837,8 +846,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
837846
#[cfg(feature = "trace")]
838847
if let Some(ref mut list) = cmd_buf.commands {
839848
list.push(TraceCommand::CopyTextureToBuffer {
840-
src: source.clone(),
841-
dst: destination.clone(),
849+
src: *source,
850+
dst: *destination,
842851
size: *copy_size,
843852
});
844853
}
@@ -1002,8 +1011,8 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
10021011
#[cfg(feature = "trace")]
10031012
if let Some(ref mut list) = cmd_buf.commands {
10041013
list.push(TraceCommand::CopyTextureToTexture {
1005-
src: source.clone(),
1006-
dst: destination.clone(),
1014+
src: *source,
1015+
dst: *destination,
10071016
size: *copy_size,
10081017
});
10091018
}

wgpu-core/src/conv.rs

+24
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,30 @@ pub fn is_valid_copy_dst_texture_format(
3333
}
3434
}
3535

36+
#[cfg_attr(
37+
any(not(target_arch = "wasm32"), feature = "emscripten"),
38+
allow(unused)
39+
)]
40+
pub fn is_valid_external_image_copy_dst_texture_format(format: wgt::TextureFormat) -> bool {
41+
use wgt::TextureFormat as Tf;
42+
match format {
43+
Tf::R8Unorm
44+
| Tf::R16Float
45+
| Tf::R32Float
46+
| Tf::Rg8Unorm
47+
| Tf::Rg16Float
48+
| Tf::Rg32Float
49+
| Tf::Rgba8Unorm
50+
| Tf::Rgba8UnormSrgb
51+
| Tf::Bgra8Unorm
52+
| Tf::Bgra8UnormSrgb
53+
| Tf::Rgb10a2Unorm
54+
| Tf::Rgba16Float
55+
| Tf::Rgba32Float => true,
56+
_ => false,
57+
}
58+
}
59+
3660
pub fn map_buffer_usage(usage: wgt::BufferUsages) -> hal::BufferUses {
3761
let mut u = hal::BufferUses::empty();
3862
u.set(

0 commit comments

Comments
 (0)