Skip to content

Commit

Permalink
allow creation of wgpu_hal textures for gles backend
Browse files Browse the repository at this point in the history
This should be enough to allow RGB external textures to work on Linux. For Android, we still need to implement logic to generate shaders with samplerOESExternal and select the correct shader depending on the type of texture being created.
  • Loading branch information
i509VCB committed Oct 13, 2022
1 parent b65ebb4 commit 0360e60
Show file tree
Hide file tree
Showing 12 changed files with 158 additions and 54 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down
10 changes: 1 addition & 9 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
125 changes: 91 additions & 34 deletions wgpu-hal/src/gles/device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use std::{
#[cfg(not(target_arch = "wasm32"))]
use std::mem;

#[cfg(any(not(target_arch = "wasm32"), feature = "emscripten"))]
use std::num::NonZeroU32;

type ShaderStage<'a> = (
naga::ShaderStage,
&'a crate::ProgrammableStage<'a, super::Api>,
Expand Down Expand Up @@ -84,6 +87,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: 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: 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 +655,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 +713,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 +727,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 @@ -295,6 +295,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 @@ -230,7 +230,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
Loading

0 comments on commit 0360e60

Please sign in to comment.