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

allow creation of wgpu_hal textures for gles backend #3046

Merged
merged 3 commits into from
Oct 13, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
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
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,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 @@ -202,6 +203,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() {
i509VCB marked this conversation as resolved.
Show resolved Hide resolved
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