Skip to content

Commit

Permalink
allow creation of wgpu_hal textures for gles backend (#3046)
Browse files Browse the repository at this point in the history
Co-authored-by: Connor Fitzgerald <[email protected]>
  • Loading branch information
i509VCB and cwfitzgerald authored Oct 13, 2022
1 parent caee97e commit 7aca31f
Show file tree
Hide file tree
Showing 12 changed files with 155 additions and 47 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ both `raw_window_handle::HasRawWindowHandle` and `raw_window_handle::HasRawDispl
- 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)
- Implemented `copy_external_image_to_texture` on WebGPU, by @ybiletskyi in [#2781](https://github.com/gfx-rs/wgpu/pull/2781)

### Bug Fixes
Expand Down Expand Up @@ -206,6 +207,7 @@ both `raw_window_handle::HasRawWindowHandle` and `raw_window_handle::HasRawDispl
- 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)

#### GLES

Expand Down
3 changes: 1 addition & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion wgpu-hal/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,9 @@ 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 }
# TODO: New glow release
glow = { git = "https://github.com/grovesNL/glow/", rev = "c8a011fcd57a5c68cc917ed394baa484bdefc909", optional = true }

# backend: Dx12
bit-set = { version = "0.5", optional = true }
Expand Down
11 changes: 11 additions & 0 deletions wgpu-hal/src/auxil/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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),
Expand Down
122 changes: 88 additions & 34 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 [`None`], wgpu-hal will take ownership of the texture. If `drop_guard` is
/// [`Some`], the texture must be valid until the drop implementation
/// of the drop guard is called.
#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
pub unsafe fn texture_from_raw(
&self,
name: std::num::NonZeroU32,
desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>,
) -> super::Texture {
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 [`None`], wgpu-hal will take ownership of the renderbuffer. If `drop_guard` is
/// [`Some`], the renderbuffer must be valid until the drop implementation
/// of the drop guard is called.
#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
pub unsafe fn texture_from_raw_renderbuffer(
&self,
name: std::num::NonZeroU32,
desc: &crate::TextureDescriptor,
drop_guard: Option<crate::DropGuard>,
) -> super::Texture {
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,
Expand Down Expand Up @@ -581,32 +652,8 @@ impl crate::Device<super::Api> 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!
Expand Down Expand Up @@ -663,6 +710,7 @@ impl crate::Device<super::Api> 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
Expand All @@ -676,16 +724,22 @@ impl crate::Device<super::Api> 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);
}
}
}

// For clarity, we explicitly drop the drop guard. Although this has no real semantic effect as the
// end of the scope will drop the drop guard since this function takes ownership of the texture.
drop(texture.drop_guard);
}

unsafe fn create_texture_view(
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/gles/egl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1241,6 +1241,7 @@ impl crate::Surface<super::Api> for Surface {
inner: super::TextureInner::Renderbuffer {
raw: sc.renderbuffer,
},
drop_guard: None,
array_layer_count: 1,
mip_level_count: 1,
format: sc.format,
Expand Down
41 changes: 39 additions & 2 deletions wgpu-hal/src/gles/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"))]
Expand Down Expand Up @@ -265,19 +267,21 @@ impl TextureInner {
#[derive(Debug)]
pub struct Texture {
inner: TextureInner,
drop_guard: Option<crate::DropGuard>,
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,
}

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,
Expand All @@ -286,14 +290,47 @@ impl Texture {
external: 0,
data_type: 0,
},
copy_size: crate::CopyExtent {
copy_size: CopyExtent {
width: 0,
height: 0,
depth: 0,
},
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)]
Expand Down
1 change: 1 addition & 0 deletions wgpu-hal/src/gles/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,7 @@ impl crate::Surface<super::Api> for Surface {
raw: self.texture.unwrap(),
target: glow::TEXTURE_2D,
},
drop_guard: None,
array_layer_count: 1,
mip_level_count: 1,
format: sc.format,
Expand Down
5 changes: 4 additions & 1 deletion wgpu-hal/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,10 @@ pub type Label<'a> = Option<&'a str>;
pub type MemoryRange = Range<wgt::BufferAddress>;
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<dyn std::any::Any + Send + Sync>;

#[derive(Clone, Debug, PartialEq, Eq, Error)]
pub enum DeviceError {
#[error("out of memory")]
OutOfMemory,
Expand Down
4 changes: 2 additions & 2 deletions wgpu-hal/src/vulkan/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -609,7 +609,7 @@ impl super::Device {
pub unsafe fn texture_from_raw(
vk_image: vk::Image,
desc: &crate::TextureDescriptor,
drop_guard: Option<super::DropGuard>,
drop_guard: Option<crate::DropGuard>,
) -> super::Texture {
super::Texture {
raw: vk_image,
Expand All @@ -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),
}
}

Expand Down
2 changes: 1 addition & 1 deletion wgpu-hal/src/vulkan/instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ impl super::Instance {
extensions: Vec<&'static CStr>,
flags: crate::InstanceFlags,
has_nv_optimus: bool,
drop_guard: Option<super::DropGuard>,
drop_guard: Option<crate::DropGuard>,
) -> Result<Self, crate::InstanceError> {
log::info!("Instance version: 0x{:x}", driver_api_version);

Expand Down
6 changes: 2 additions & 4 deletions wgpu-hal/src/vulkan/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<dyn std::any::Any + Send + Sync>;

#[derive(Clone)]
pub struct Api;

Expand Down Expand Up @@ -82,7 +80,7 @@ struct DebugUtils {
pub struct InstanceShared {
raw: ash::Instance,
extensions: Vec<&'static CStr>,
drop_guard: Option<DropGuard>,
drop_guard: Option<crate::DropGuard>,
flags: crate::InstanceFlags,
debug_utils: Option<DebugUtils>,
get_physical_device_properties: Option<khr::GetPhysicalDeviceProperties2>,
Expand Down Expand Up @@ -347,7 +345,7 @@ pub struct Buffer {
#[derive(Debug)]
pub struct Texture {
raw: vk::Image,
drop_guard: Option<DropGuard>,
drop_guard: Option<crate::DropGuard>,
block: Option<gpu_alloc::MemoryBlock<vk::DeviceMemory>>,
usage: crate::TextureUses,
aspects: crate::FormatAspects,
Expand Down

0 comments on commit 7aca31f

Please sign in to comment.