diff --git a/CHANGELOG.md b/CHANGELOG.md index 6fd4e5348e5..bb6b6f2f862 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -75,6 +75,7 @@ SurfaceConfiguration { - Split Blendability and Filterability into Two Different TextureFormatFeatureFlags; by @stakka in [#3012](https://github.com/gfx-rs/wgpu/pull/3012) - Expose `alpha_mode` on SurfaceConfiguration, by @jinleili in [#2836](https://github.com/gfx-rs/wgpu/pull/2836) - Introduce fields for driver name and info in `AdapterInfo`, by @i509VCB in [#3037](https://github.com/gfx-rs/wgpu/pull/3037) +- Add way to create gles hal textures from raw gl names to allow externally managed textures. By @i509VCB [#3046](https://github.com/gfx-rs/wgpu/pull/3046) ### Bug Fixes @@ -126,6 +127,7 @@ SurfaceConfiguration { - Provide a means for `wgpu` users to access `vk::Queue` and the queue index. By @anlumo in [#2950](https://github.com/gfx-rs/wgpu/pull/2950) - Use the use effective api version for determining device features instead of wrongly assuming `VkPhysicalDeviceProperties.apiVersion` is the actual version of the device. By @i509VCB in [#3011](https://github.com/gfx-rs/wgpu/pull/3011) +- `DropGuard` has been moved to the root of the wgpu-hal crate. By @i509VCB [#3046](https://github.com/gfx-rs/wgpu/pull/3046) ### Performance diff --git a/Cargo.lock b/Cargo.lock index 5e2ac814c2a..8401afea738 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -337,12 +337,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "copyless" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2df960f5d869b2dd8532793fde43eb5427cceb126c929747a26823ab0eeb536" - [[package]] name = "core-foundation" version = "0.9.3" @@ -754,8 +748,7 @@ checksum = "518faa5064866338b013ff9b2350dc318e14cc4fcd6cb8206d7e7c9886c98815" [[package]] name = "glow" version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d8bd5877156a19b8ac83a29b2306fe20537429d318f3ff0a1a2119f8d9c61919" +source = "git+https://github.com/grovesNL/glow/?rev=c8a011fcd57a5c68cc917ed394baa484bdefc909#c8a011fcd57a5c68cc917ed394baa484bdefc909" dependencies = [ "js-sys", "slotmap", @@ -2249,7 +2242,6 @@ dependencies = [ "bitflags", "cfg_aliases", "codespan-reporting", - "copyless", "fxhash", "log", "naga", diff --git a/Cargo.toml b/Cargo.toml index 7d3044ae3d9..11fbbc7d6d7 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,6 +28,7 @@ default-members = ["wgpu", "wgpu-hal", "wgpu-info"] [patch.crates-io] #naga = { path = "../naga" } #glow = { path = "../glow" } +glow = { git = "https://github.com/grovesNL/glow/", rev = "c8a011fcd57a5c68cc917ed394baa484bdefc909" } #d3d12 = { path = "../d3d12-rs" } #metal = { path = "../metal-rs" } #web-sys = { path = "../wasm-bindgen/crates/web-sys" } diff --git a/wgpu-hal/Cargo.toml b/wgpu-hal/Cargo.toml index a8cfe5e4a4e..9fdf9293362 100644 --- a/wgpu-hal/Cargo.toml +++ b/wgpu-hal/Cargo.toml @@ -54,7 +54,7 @@ gpu-descriptor = { version = "0.2", optional = true } smallvec = { version = "1", optional = true, features = ["union"] } # backend: Gles -glow = { version = "0.11.1", optional = true } +glow = { version = "0.11.2", optional = true } # backend: Dx12 bit-set = { version = "0.5", optional = true } diff --git a/wgpu-hal/src/auxil/mod.rs b/wgpu-hal/src/auxil/mod.rs index d8675ac0d02..8d29021726a 100644 --- a/wgpu-hal/src/auxil/mod.rs +++ b/wgpu-hal/src/auxil/mod.rs @@ -66,6 +66,17 @@ pub fn align_to(value: u32, alignment: u32) -> u32 { } impl crate::CopyExtent { + pub fn map_extent_to_copy_size(extent: &wgt::Extent3d, dim: wgt::TextureDimension) -> Self { + Self { + width: extent.width, + height: extent.height, + depth: match dim { + wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => 1, + wgt::TextureDimension::D3 => extent.depth_or_array_layers, + }, + } + } + pub fn min(&self, other: &Self) -> Self { Self { width: self.width.min(other.width), diff --git a/wgpu-hal/src/gles/device.rs b/wgpu-hal/src/gles/device.rs index 04ecdffe02d..e21d1ff7293 100644 --- a/wgpu-hal/src/gles/device.rs +++ b/wgpu-hal/src/gles/device.rs @@ -84,6 +84,77 @@ impl CompilationContext<'_> { } impl super::Device { + /// # Safety + /// + /// - `name` must be created respecting `desc` + /// - `name` must be a texture + /// - If `drop_guard` is `Some`, the application must manually destroy the texture id. This + /// can be done inside the `Drop` impl of `drop_guard`. + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] // create_texture_from_gl_name is only available on native. + pub unsafe fn texture_from_raw( + &self, + name: u32, + desc: &crate::TextureDescriptor, + drop_guard: Option, + ) -> super::Texture { + let name = std::num::NonZeroU32::new(name).expect("Invalid GL name"); + let mut copy_size = crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension); + + let (target, _, is_cubemap) = super::Texture::get_info_from_desc(&mut copy_size, desc); + + super::Texture { + inner: super::TextureInner::Texture { + raw: glow::NativeTexture(name), + target, + }, + drop_guard, + mip_level_count: desc.mip_level_count, + array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { + desc.size.depth_or_array_layers + } else { + 1 + }, + format: desc.format, + format_desc: self.shared.describe_texture_format(desc.format), + copy_size, + is_cubemap, + } + } + + /// # Safety + /// + /// - `name` must be created respecting `desc` + /// - `name` must be a renderbuffer + /// - If `drop_guard` is `Some`, the application must manually destroy the texture id. This + /// can be done inside the `Drop` impl of `drop_guard`. + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] + pub unsafe fn texture_from_raw_renderbuffer( + &self, + name: u32, + desc: &crate::TextureDescriptor, + drop_guard: Option, + ) -> super::Texture { + let name = std::num::NonZeroU32::new(name).expect("Invalid GL name"); + let copy_size = crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension); + + super::Texture { + inner: super::TextureInner::Renderbuffer { + raw: glow::NativeRenderbuffer(name), + }, + drop_guard, + mip_level_count: desc.mip_level_count, + array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { + desc.size.depth_or_array_layers + } else { + 1 + }, + format: desc.format, + format_desc: self.shared.describe_texture_format(desc.format), + copy_size, + is_cubemap: false, + } + } + unsafe fn compile_shader( gl: &glow::Context, shader: &str, @@ -581,32 +652,8 @@ impl crate::Device for super::Device { (super::TextureInner::Renderbuffer { raw }, false) } else { let raw = gl.create_texture().unwrap(); - let (target, is_3d, is_cubemap) = match desc.dimension { - wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { - if desc.size.depth_or_array_layers > 1 { - //HACK: detect a cube map - let cube_count = if desc.size.width == desc.size.height - && desc.size.depth_or_array_layers % 6 == 0 - && desc.sample_count == 1 - { - Some(desc.size.depth_or_array_layers / 6) - } else { - None - }; - match cube_count { - None => (glow::TEXTURE_2D_ARRAY, true, false), - Some(1) => (glow::TEXTURE_CUBE_MAP, false, true), - Some(_) => (glow::TEXTURE_CUBE_MAP_ARRAY, true, true), - } - } else { - (glow::TEXTURE_2D, false, false) - } - } - wgt::TextureDimension::D3 => { - copy_size.depth = desc.size.depth_or_array_layers; - (glow::TEXTURE_3D, true, false) - } - }; + let (target, is_3d, is_cubemap) = + super::Texture::get_info_from_desc(&mut copy_size, desc); gl.bind_texture(target, Some(raw)); //Note: this has to be done before defining the storage! @@ -663,6 +710,7 @@ impl crate::Device for super::Device { Ok(super::Texture { inner, + drop_guard: None, mip_level_count: desc.mip_level_count, array_layer_count: if desc.dimension == wgt::TextureDimension::D2 { desc.size.depth_or_array_layers @@ -676,14 +724,16 @@ impl crate::Device for super::Device { }) } unsafe fn destroy_texture(&self, texture: super::Texture) { - let gl = &self.shared.context.lock(); - match texture.inner { - super::TextureInner::Renderbuffer { raw, .. } => { - gl.delete_renderbuffer(raw); - } - super::TextureInner::DefaultRenderbuffer => {} - super::TextureInner::Texture { raw, .. } => { - gl.delete_texture(raw); + if texture.drop_guard.is_none() { + let gl = &self.shared.context.lock(); + match texture.inner { + super::TextureInner::Renderbuffer { raw, .. } => { + gl.delete_renderbuffer(raw); + } + super::TextureInner::DefaultRenderbuffer => {} + super::TextureInner::Texture { raw, .. } => { + gl.delete_texture(raw); + } } } } diff --git a/wgpu-hal/src/gles/egl.rs b/wgpu-hal/src/gles/egl.rs index 32264276c6b..1f4cae00a17 100644 --- a/wgpu-hal/src/gles/egl.rs +++ b/wgpu-hal/src/gles/egl.rs @@ -1241,6 +1241,7 @@ impl crate::Surface for Surface { inner: super::TextureInner::Renderbuffer { raw: sc.renderbuffer, }, + drop_guard: None, array_layer_count: 1, mip_level_count: 1, format: sc.format, diff --git a/wgpu-hal/src/gles/mod.rs b/wgpu-hal/src/gles/mod.rs index 717502f2c6c..0017552db11 100644 --- a/wgpu-hal/src/gles/mod.rs +++ b/wgpu-hal/src/gles/mod.rs @@ -68,6 +68,8 @@ mod conv; mod device; mod queue; +use crate::{CopyExtent, TextureDescriptor}; + #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] pub use self::egl::{AdapterContext, AdapterContextLock}; #[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))] @@ -265,12 +267,13 @@ impl TextureInner { #[derive(Debug)] pub struct Texture { inner: TextureInner, + drop_guard: Option, mip_level_count: u32, array_layer_count: u32, format: wgt::TextureFormat, #[allow(unused)] format_desc: TextureFormatDesc, - copy_size: crate::CopyExtent, + copy_size: CopyExtent, is_cubemap: bool, } @@ -278,6 +281,7 @@ impl Texture { pub fn default_framebuffer(format: wgt::TextureFormat) -> Self { Self { inner: TextureInner::DefaultRenderbuffer, + drop_guard: None, mip_level_count: 1, array_layer_count: 1, format, @@ -286,7 +290,7 @@ impl Texture { external: 0, data_type: 0, }, - copy_size: crate::CopyExtent { + copy_size: CopyExtent { width: 0, height: 0, depth: 0, @@ -294,6 +298,39 @@ impl Texture { is_cubemap: false, } } + + /// Returns the `target`, whether the image is 3d and whether the image is a cubemap. + fn get_info_from_desc( + copy_size: &mut CopyExtent, + desc: &TextureDescriptor, + ) -> (u32, bool, bool) { + match desc.dimension { + wgt::TextureDimension::D1 | wgt::TextureDimension::D2 => { + if desc.size.depth_or_array_layers > 1 { + //HACK: detect a cube map + let cube_count = if desc.size.width == desc.size.height + && desc.size.depth_or_array_layers % 6 == 0 + && desc.sample_count == 1 + { + Some(desc.size.depth_or_array_layers / 6) + } else { + None + }; + match cube_count { + None => (glow::TEXTURE_2D_ARRAY, true, false), + Some(1) => (glow::TEXTURE_CUBE_MAP, false, true), + Some(_) => (glow::TEXTURE_CUBE_MAP_ARRAY, true, true), + } + } else { + (glow::TEXTURE_2D, false, false) + } + } + wgt::TextureDimension::D3 => { + copy_size.depth = desc.size.depth_or_array_layers; + (glow::TEXTURE_3D, true, false) + } + } + } } #[derive(Clone, Debug)] diff --git a/wgpu-hal/src/gles/web.rs b/wgpu-hal/src/gles/web.rs index 396fdad04bf..6acc6288c4a 100644 --- a/wgpu-hal/src/gles/web.rs +++ b/wgpu-hal/src/gles/web.rs @@ -295,6 +295,7 @@ impl crate::Surface for Surface { raw: self.texture.unwrap(), target: glow::TEXTURE_2D, }, + drop_guard: None, array_layer_count: 1, mip_level_count: 1, format: sc.format, diff --git a/wgpu-hal/src/lib.rs b/wgpu-hal/src/lib.rs index cbaf803d9a8..a77b02ac67b 100644 --- a/wgpu-hal/src/lib.rs +++ b/wgpu-hal/src/lib.rs @@ -106,7 +106,10 @@ pub type Label<'a> = Option<&'a str>; pub type MemoryRange = Range; pub type FenceValue = u64; -#[derive(Clone, Debug, Eq, PartialEq, Error)] +/// Drop guard to signal wgpu-hal is no longer using an externally created object. +pub type DropGuard = Box; + +#[derive(Clone, Debug, PartialEq, Eq, Error)] pub enum DeviceError { #[error("out of memory")] OutOfMemory, diff --git a/wgpu-hal/src/vulkan/device.rs b/wgpu-hal/src/vulkan/device.rs index b9d74e36e35..8f6b9c16b0b 100644 --- a/wgpu-hal/src/vulkan/device.rs +++ b/wgpu-hal/src/vulkan/device.rs @@ -609,7 +609,7 @@ impl super::Device { pub unsafe fn texture_from_raw( vk_image: vk::Image, desc: &crate::TextureDescriptor, - drop_guard: Option, + drop_guard: Option, ) -> super::Texture { super::Texture { raw: vk_image, @@ -619,7 +619,7 @@ impl super::Device { aspects: crate::FormatAspects::from(desc.format), format_info: desc.format.describe(), raw_flags: vk::ImageCreateFlags::empty(), - copy_size: conv::map_extent_to_copy_size(&desc.size, desc.dimension), + copy_size: crate::CopyExtent::map_extent_to_copy_size(&desc.size, desc.dimension), } } diff --git a/wgpu-hal/src/vulkan/instance.rs b/wgpu-hal/src/vulkan/instance.rs index 79045ff061a..43fd649ca24 100644 --- a/wgpu-hal/src/vulkan/instance.rs +++ b/wgpu-hal/src/vulkan/instance.rs @@ -230,7 +230,7 @@ impl super::Instance { extensions: Vec<&'static CStr>, flags: crate::InstanceFlags, has_nv_optimus: bool, - drop_guard: Option, + drop_guard: Option, ) -> Result { log::info!("Instance version: 0x{:x}", driver_api_version); diff --git a/wgpu-hal/src/vulkan/mod.rs b/wgpu-hal/src/vulkan/mod.rs index d3416a50ed9..bb139c78d26 100644 --- a/wgpu-hal/src/vulkan/mod.rs +++ b/wgpu-hal/src/vulkan/mod.rs @@ -43,8 +43,6 @@ use parking_lot::Mutex; const MILLIS_TO_NANOS: u64 = 1_000_000; const MAX_TOTAL_ATTACHMENTS: usize = crate::MAX_COLOR_ATTACHMENTS * 2 + 1; -pub type DropGuard = Box; - #[derive(Clone)] pub struct Api; @@ -82,7 +80,7 @@ struct DebugUtils { pub struct InstanceShared { raw: ash::Instance, extensions: Vec<&'static CStr>, - drop_guard: Option, + drop_guard: Option, flags: crate::InstanceFlags, debug_utils: Option, get_physical_device_properties: Option, @@ -347,7 +345,7 @@ pub struct Buffer { #[derive(Debug)] pub struct Texture { raw: vk::Image, - drop_guard: Option, + drop_guard: Option, block: Option>, usage: crate::TextureUses, aspects: crate::FormatAspects,