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

This commit is contained in:
Ashley 2023-01-24 19:47:03 +01:00 committed by GitHub
parent 95a760bb42
commit c039a74884
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 65 additions and 25 deletions

View File

@ -452,6 +452,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()
@ -514,10 +528,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));
}
}
}

View File

@ -813,6 +813,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 { .. } => {}
}
}

View File

@ -187,10 +187,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 {
@ -249,7 +249,7 @@ unsafe impl Sync for Buffer {}
unsafe impl Send for Buffer {}
#[derive(Clone, Debug)]
enum TextureInner {
pub enum TextureInner {
Renderbuffer {
raw: glow::Renderbuffer,
},
@ -258,8 +258,18 @@ 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 {
@ -267,21 +277,23 @@ impl TextureInner {
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 {

View File

@ -143,6 +143,10 @@ impl super::Queue {
};
}
}
#[cfg(all(target_arch = "wasm32", not(target_os = "emscripten")))]
super::TextureInner::ExternalFramebuffer { ref inner } => unsafe {
gl.bind_external_framebuffer(glow::FRAMEBUFFER, inner);
},
}
}

View File

@ -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 {

View File

@ -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,

View File

@ -2118,7 +2118,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,