Skip to content
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

[WebGL] Allow creating a texture from an external web_sys::WebGlFramebuffer and writing to it #2609

Merged
merged 5 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 20 additions & 4 deletions wgpu-hal/src/gles/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,20 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
self.state.has_pass_label = true;
}

let rendering_to_external_framebuffer = desc
.color_attachments
.iter()
.filter_map(|at| at.as_ref())
.any(|at| match at.target.view.inner {
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
super::TextureInner::ExternalFramebuffer { .. } => true,
_ => false,
});

if rendering_to_external_framebuffer && desc.color_attachments.len() != 1 {
panic!("Multiple render attachments with external framebuffers are not supported.");
}

match desc
.color_attachments
.first()
Expand Down Expand Up @@ -489,10 +503,12 @@ impl crate::CommandEncoder<super::Api> for super::CommandEncoder {
}
}

// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
if !rendering_to_external_framebuffer {
// set the draw buffers and states
self.cmd_buffer
.commands
.push(C::SetDrawColorBuffers(desc.color_attachments.len() as u8));
}
}
}

Expand Down
2 changes: 2 additions & 0 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -761,6 +761,8 @@ impl crate::Device<super::Api> for super::Device {
super::TextureInner::Texture { raw, .. } => {
unsafe { gl.delete_texture(raw) };
}
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
super::TextureInner::ExternalFramebuffer { .. } => {}
}
}

Expand Down
38 changes: 25 additions & 13 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -184,10 +184,10 @@ impl Default for VertexAttribKind {
}

#[derive(Clone, Debug)]
struct TextureFormatDesc {
internal: u32,
external: u32,
data_type: u32,
pub struct TextureFormatDesc {
pub internal: u32,
pub external: u32,
pub data_type: u32,
}

struct AdapterShared {
Expand Down Expand Up @@ -244,7 +244,7 @@ unsafe impl Sync for Buffer {}
unsafe impl Send for Buffer {}

#[derive(Clone, Debug)]
enum TextureInner {
pub enum TextureInner {
Renderbuffer {
raw: glow::Renderbuffer,
},
Expand All @@ -253,30 +253,42 @@ enum TextureInner {
raw: glow::Texture,
target: BindTarget,
},
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
ExternalFramebuffer {
inner: web_sys::WebGlFramebuffer,
},
}

// SAFE: WASM doesn't have threads
#[cfg(target_arch = "wasm32")]
unsafe impl Send for TextureInner {}
#[cfg(target_arch = "wasm32")]
unsafe impl Sync for TextureInner {}

impl TextureInner {
fn as_native(&self) -> (glow::Texture, BindTarget) {
match *self {
Self::Renderbuffer { .. } | Self::DefaultRenderbuffer => {
panic!("Unexpected renderbuffer");
}
Self::Texture { raw, target } => (raw, target),
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
Self::ExternalFramebuffer { .. } => panic!("Unexpected external framebuffer"),
}
}
}

#[derive(Debug)]
pub struct Texture {
inner: TextureInner,
drop_guard: Option<crate::DropGuard>,
mip_level_count: u32,
array_layer_count: u32,
format: wgt::TextureFormat,
pub inner: TextureInner,
pub drop_guard: Option<crate::DropGuard>,
pub mip_level_count: u32,
pub array_layer_count: u32,
pub format: wgt::TextureFormat,
#[allow(unused)]
format_desc: TextureFormatDesc,
copy_size: CopyExtent,
is_cubemap: bool,
pub format_desc: TextureFormatDesc,
pub copy_size: CopyExtent,
pub is_cubemap: bool,
}

impl Texture {
Expand Down
4 changes: 4 additions & 0 deletions wgpu-hal/src/gles/queue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,10 @@ impl super::Queue {
};
}
}
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
super::TextureInner::ExternalFramebuffer { ref inner } => {
gl.bind_external_framebuffer(glow::FRAMEBUFFER, inner);
}
}
}

Expand Down
18 changes: 12 additions & 6 deletions wgpu-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,23 @@ compile_error!("Metal API enabled on non-Apple OS. If your project is not using
#[cfg(all(feature = "dx12", not(windows)))]
compile_error!("DX12 API enabled on non-Windows OS. If your project is not using resolver=\"2\" in Cargo.toml, it should.");

/// DirectX11 API internals.
#[cfg(all(feature = "dx11", windows))]
mod dx11;
pub mod dx11;
/// DirectX12 API internals.
#[cfg(all(feature = "dx12", windows))]
mod dx12;
mod empty;
pub mod dx12;
/// A dummy API implementation.
pub mod empty;
/// GLES API internals.
#[cfg(all(feature = "gles"))]
mod gles;
pub mod gles;
/// Metal API internals.
#[cfg(all(feature = "metal"))]
mod metal;
pub mod metal;
/// Vulkan API internals.
#[cfg(feature = "vulkan")]
mod vulkan;
pub mod vulkan;

pub mod auxil;
pub mod api {
Expand Down
2 changes: 1 addition & 1 deletion wgpu/src/backend/direct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,7 @@ impl Context {
Ok((device, queue))
}

#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten", feature = "webgl"))]
pub unsafe fn create_texture_from_hal<A: wgc::hub::HalApi>(
&self,
hal_texture: A::Texture,
Expand Down
2 changes: 1 addition & 1 deletion wgpu/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2066,7 +2066,7 @@ impl Device {
/// - `hal_texture` must be created from this device internal handle
/// - `hal_texture` must be created respecting `desc`
/// - `hal_texture` must be initialized
#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten", feature = "webgl"))]
pub unsafe fn create_texture_from_hal<A: wgc::hub::HalApi>(
&self,
hal_texture: A::Texture,
Expand Down