mirror of
https://github.com/gfx-rs/wgpu.git
synced 2024-11-22 06:44:14 +00:00
Fix surfaces only compatible with first enabled backend (#5535)
This commit is contained in:
parent
ea77d5674d
commit
cbace631ec
@ -153,6 +153,7 @@ Bottom level categories:
|
|||||||
- Failing to set the device lost closure will call the closure before returning. By @bradwerth in [#5358](https://github.com/gfx-rs/wgpu/pull/5358).
|
- Failing to set the device lost closure will call the closure before returning. By @bradwerth in [#5358](https://github.com/gfx-rs/wgpu/pull/5358).
|
||||||
- Use memory pooling for UsageScopes to avoid frequent large allocations. by @robtfm in [#5414](https://github.com/gfx-rs/wgpu/pull/5414)
|
- Use memory pooling for UsageScopes to avoid frequent large allocations. by @robtfm in [#5414](https://github.com/gfx-rs/wgpu/pull/5414)
|
||||||
- Fix deadlocks caused by recursive read-write lock acquisitions [#5426](https://github.com/gfx-rs/wgpu/pull/5426).
|
- Fix deadlocks caused by recursive read-write lock acquisitions [#5426](https://github.com/gfx-rs/wgpu/pull/5426).
|
||||||
|
- Fix surfaces being only compatible with first backend enabled on an instance, causing failures when manually specifying an adapter. By @Wumpf in [#5535](https://github.com/gfx-rs/wgpu/pull/5535).
|
||||||
|
|
||||||
#### Naga
|
#### Naga
|
||||||
- In spv-in, remove unnecessary "gl_PerVertex" name check so unused builtins will always be skipped. By @Imberflur in [#5227](https://github.com/gfx-rs/wgpu/pull/5227).
|
- In spv-in, remove unnecessary "gl_PerVertex" name check so unused builtins will always be skipped. By @Imberflur in [#5227](https://github.com/gfx-rs/wgpu/pull/5227).
|
||||||
|
@ -1,95 +0,0 @@
|
|||||||
use wgt::Backend;
|
|
||||||
|
|
||||||
/// The `AnySurface` type: a `Arc` of a `A::Surface` for any backend `A`.
|
|
||||||
use crate::hal_api::HalApi;
|
|
||||||
|
|
||||||
use std::fmt;
|
|
||||||
use std::mem::ManuallyDrop;
|
|
||||||
use std::ptr::NonNull;
|
|
||||||
|
|
||||||
struct AnySurfaceVtable {
|
|
||||||
// We oppurtunistically store the backend here, since we now it will be used
|
|
||||||
// with backend selection and it can be stored in static memory.
|
|
||||||
backend: Backend,
|
|
||||||
// Drop glue which knows how to drop the stored data.
|
|
||||||
drop: unsafe fn(*mut ()),
|
|
||||||
}
|
|
||||||
|
|
||||||
/// An `A::Surface`, for any backend `A`.
|
|
||||||
///
|
|
||||||
/// Any `AnySurface` is just like an `A::Surface`, except that the `A` type
|
|
||||||
/// parameter is erased. To access the `Surface`, you must downcast to a
|
|
||||||
/// particular backend with the \[`downcast_ref`\] or \[`take`\] methods.
|
|
||||||
pub struct AnySurface {
|
|
||||||
data: NonNull<()>,
|
|
||||||
vtable: &'static AnySurfaceVtable,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl AnySurface {
|
|
||||||
/// Construct an `AnySurface` that owns an `A::Surface`.
|
|
||||||
pub fn new<A: HalApi>(surface: A::Surface) -> AnySurface {
|
|
||||||
unsafe fn drop_glue<A: HalApi>(ptr: *mut ()) {
|
|
||||||
unsafe {
|
|
||||||
_ = Box::from_raw(ptr.cast::<A::Surface>());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let data = NonNull::from(Box::leak(Box::new(surface)));
|
|
||||||
|
|
||||||
AnySurface {
|
|
||||||
data: data.cast(),
|
|
||||||
vtable: &AnySurfaceVtable {
|
|
||||||
backend: A::VARIANT,
|
|
||||||
drop: drop_glue::<A>,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Get the backend this surface was created through.
|
|
||||||
pub fn backend(&self) -> Backend {
|
|
||||||
self.vtable.backend
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If `self` refers to an `A::Surface`, returns a reference to it.
|
|
||||||
pub fn downcast_ref<A: HalApi>(&self) -> Option<&A::Surface> {
|
|
||||||
if A::VARIANT != self.vtable.backend {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// SAFETY: We just checked the instance above implicitly by the backend
|
|
||||||
// that it was statically constructed through.
|
|
||||||
Some(unsafe { &*self.data.as_ptr().cast::<A::Surface>() })
|
|
||||||
}
|
|
||||||
|
|
||||||
/// If `self` is an `Arc<A::Surface>`, returns that.
|
|
||||||
pub fn take<A: HalApi>(self) -> Option<A::Surface> {
|
|
||||||
if A::VARIANT != self.vtable.backend {
|
|
||||||
return None;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Disable drop glue, since we're returning the owned surface. The
|
|
||||||
// caller will be responsible for dropping it.
|
|
||||||
let this = ManuallyDrop::new(self);
|
|
||||||
|
|
||||||
// SAFETY: We just checked the instance above implicitly by the backend
|
|
||||||
// that it was statically constructed through.
|
|
||||||
Some(unsafe { *Box::from_raw(this.data.as_ptr().cast::<A::Surface>()) })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for AnySurface {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { (self.vtable.drop)(self.data.as_ptr()) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl fmt::Debug for AnySurface {
|
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
||||||
write!(f, "AnySurface<{}>", self.vtable.backend)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[cfg(send_sync)]
|
|
||||||
unsafe impl Send for AnySurface {}
|
|
||||||
#[cfg(send_sync)]
|
|
||||||
unsafe impl Sync for AnySurface {}
|
|
@ -1969,7 +1969,7 @@ impl Global {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let caps = unsafe {
|
let caps = unsafe {
|
||||||
let suf = A::get_surface(surface);
|
let suf = A::surface_as_hal(surface);
|
||||||
let adapter = &device.adapter;
|
let adapter = &device.adapter;
|
||||||
match adapter.raw.adapter.surface_capabilities(suf.unwrap()) {
|
match adapter.raw.adapter.surface_capabilities(suf.unwrap()) {
|
||||||
Some(caps) => caps,
|
Some(caps) => caps,
|
||||||
@ -2055,7 +2055,7 @@ impl Global {
|
|||||||
// https://github.com/gfx-rs/wgpu/issues/4105
|
// https://github.com/gfx-rs/wgpu/issues/4105
|
||||||
|
|
||||||
match unsafe {
|
match unsafe {
|
||||||
A::get_surface(surface)
|
A::surface_as_hal(surface)
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.configure(device.raw(), &hal_config)
|
.configure(device.raw(), &hal_config)
|
||||||
} {
|
} {
|
||||||
|
@ -11,7 +11,7 @@ pub trait HalApi: hal::Api + 'static + WasmNotSendSync {
|
|||||||
fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance;
|
fn create_instance_from_hal(name: &str, hal_instance: Self::Instance) -> Instance;
|
||||||
fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance>;
|
fn instance_as_hal(instance: &Instance) -> Option<&Self::Instance>;
|
||||||
fn hub(global: &Global) -> &Hub<Self>;
|
fn hub(global: &Global) -> &Hub<Self>;
|
||||||
fn get_surface(surface: &Surface) -> Option<&Self::Surface>;
|
fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface>;
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HalApi for hal::api::Empty {
|
impl HalApi for hal::api::Empty {
|
||||||
@ -25,7 +25,7 @@ impl HalApi for hal::api::Empty {
|
|||||||
fn hub(_: &Global) -> &Hub<Self> {
|
fn hub(_: &Global) -> &Hub<Self> {
|
||||||
unimplemented!("called empty api")
|
unimplemented!("called empty api")
|
||||||
}
|
}
|
||||||
fn get_surface(_: &Surface) -> Option<&Self::Surface> {
|
fn surface_as_hal(_: &Surface) -> Option<&Self::Surface> {
|
||||||
unimplemented!("called empty api")
|
unimplemented!("called empty api")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -46,8 +46,8 @@ impl HalApi for hal::api::Vulkan {
|
|||||||
fn hub(global: &Global) -> &Hub<Self> {
|
fn hub(global: &Global) -> &Hub<Self> {
|
||||||
&global.hubs.vulkan
|
&global.hubs.vulkan
|
||||||
}
|
}
|
||||||
fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
|
fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
|
||||||
surface.raw.downcast_ref::<Self>()
|
surface.vulkan.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -67,8 +67,8 @@ impl HalApi for hal::api::Metal {
|
|||||||
fn hub(global: &Global) -> &Hub<Self> {
|
fn hub(global: &Global) -> &Hub<Self> {
|
||||||
&global.hubs.metal
|
&global.hubs.metal
|
||||||
}
|
}
|
||||||
fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
|
fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
|
||||||
surface.raw.downcast_ref::<Self>()
|
surface.metal.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +88,8 @@ impl HalApi for hal::api::Dx12 {
|
|||||||
fn hub(global: &Global) -> &Hub<Self> {
|
fn hub(global: &Global) -> &Hub<Self> {
|
||||||
&global.hubs.dx12
|
&global.hubs.dx12
|
||||||
}
|
}
|
||||||
fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
|
fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
|
||||||
surface.raw.downcast_ref::<Self>()
|
surface.dx12.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,7 +110,7 @@ impl HalApi for hal::api::Gles {
|
|||||||
fn hub(global: &Global) -> &Hub<Self> {
|
fn hub(global: &Global) -> &Hub<Self> {
|
||||||
&global.hubs.gl
|
&global.hubs.gl
|
||||||
}
|
}
|
||||||
fn get_surface(surface: &Surface) -> Option<&Self::Surface> {
|
fn surface_as_hal(surface: &Surface) -> Option<&Self::Surface> {
|
||||||
surface.raw.downcast_ref::<Self>()
|
surface.gl.as_ref()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -241,7 +241,7 @@ impl<A: HalApi> Hub<A> {
|
|||||||
if let Element::Occupied(ref surface, _epoch) = *element {
|
if let Element::Occupied(ref surface, _epoch) = *element {
|
||||||
if let Some(ref mut present) = surface.presentation.lock().take() {
|
if let Some(ref mut present) = surface.presentation.lock().take() {
|
||||||
if let Some(device) = present.device.downcast_ref::<A>() {
|
if let Some(device) = present.device.downcast_ref::<A>() {
|
||||||
let suf = A::get_surface(surface);
|
let suf = A::surface_as_hal(surface);
|
||||||
unsafe {
|
unsafe {
|
||||||
suf.unwrap().unconfigure(device.raw());
|
suf.unwrap().unconfigure(device.raw());
|
||||||
//TODO: we could destroy the surface here
|
//TODO: we could destroy the surface here
|
||||||
|
@ -1,13 +1,12 @@
|
|||||||
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
any_surface::AnySurface,
|
|
||||||
api_log,
|
api_log,
|
||||||
device::{queue::Queue, resource::Device, DeviceDescriptor},
|
device::{queue::Queue, resource::Device, DeviceDescriptor},
|
||||||
global::Global,
|
global::Global,
|
||||||
hal_api::HalApi,
|
hal_api::HalApi,
|
||||||
id::markers,
|
id::{markers, AdapterId, DeviceId, Id, Marker, QueueId, SurfaceId},
|
||||||
id::{AdapterId, DeviceId, Id, Marker, QueueId, SurfaceId},
|
|
||||||
present::Presentation,
|
present::Presentation,
|
||||||
resource::{Resource, ResourceInfo, ResourceType},
|
resource::{Resource, ResourceInfo, ResourceType},
|
||||||
resource_log, LabelHelpers, DOWNLEVEL_WARNING_MESSAGE,
|
resource_log, LabelHelpers, DOWNLEVEL_WARNING_MESSAGE,
|
||||||
@ -21,6 +20,7 @@ use thiserror::Error;
|
|||||||
|
|
||||||
pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
|
pub type RequestAdapterOptions = wgt::RequestAdapterOptions<SurfaceId>;
|
||||||
type HalInstance<A> = <A as hal::Api>::Instance;
|
type HalInstance<A> = <A as hal::Api>::Instance;
|
||||||
|
type HalSurface<A> = <A as hal::Api>::Surface;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
|
#[error("Limit '{name}' value {requested} is better than allowed {allowed}")]
|
||||||
@ -113,31 +113,36 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn destroy_surface(&self, surface: Surface) {
|
pub(crate) fn destroy_surface(&self, surface: Surface) {
|
||||||
fn destroy<A: HalApi>(instance: &Option<A::Instance>, surface: AnySurface) {
|
fn destroy<A: HalApi>(instance: &Option<A::Instance>, mut surface: Option<HalSurface<A>>) {
|
||||||
unsafe {
|
if let Some(surface) = surface.take() {
|
||||||
if let Some(suf) = surface.take::<A>() {
|
unsafe {
|
||||||
instance.as_ref().unwrap().destroy_surface(suf);
|
instance.as_ref().unwrap().destroy_surface(surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
match surface.raw.backend() {
|
#[cfg(vulkan)]
|
||||||
#[cfg(vulkan)]
|
destroy::<hal::api::Vulkan>(&self.vulkan, surface.vulkan);
|
||||||
Backend::Vulkan => destroy::<hal::api::Vulkan>(&self.vulkan, surface.raw),
|
#[cfg(metal)]
|
||||||
#[cfg(metal)]
|
destroy::<hal::api::Metal>(&self.metal, surface.metal);
|
||||||
Backend::Metal => destroy::<hal::api::Metal>(&self.metal, surface.raw),
|
#[cfg(dx12)]
|
||||||
#[cfg(dx12)]
|
destroy::<hal::api::Dx12>(&self.dx12, surface.dx12);
|
||||||
Backend::Dx12 => destroy::<hal::api::Dx12>(&self.dx12, surface.raw),
|
#[cfg(gles)]
|
||||||
#[cfg(gles)]
|
destroy::<hal::api::Gles>(&self.gl, surface.gl);
|
||||||
Backend::Gl => destroy::<hal::api::Gles>(&self.gl, surface.raw),
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Surface {
|
pub struct Surface {
|
||||||
pub(crate) presentation: Mutex<Option<Presentation>>,
|
pub(crate) presentation: Mutex<Option<Presentation>>,
|
||||||
pub(crate) info: ResourceInfo<Surface>,
|
pub(crate) info: ResourceInfo<Surface>,
|
||||||
pub(crate) raw: AnySurface,
|
|
||||||
|
#[cfg(vulkan)]
|
||||||
|
pub vulkan: Option<HalSurface<hal::api::Vulkan>>,
|
||||||
|
#[cfg(metal)]
|
||||||
|
pub metal: Option<HalSurface<hal::api::Metal>>,
|
||||||
|
#[cfg(dx12)]
|
||||||
|
pub dx12: Option<HalSurface<hal::api::Dx12>>,
|
||||||
|
#[cfg(gles)]
|
||||||
|
pub gl: Option<HalSurface<hal::api::Gles>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resource for Surface {
|
impl Resource for Surface {
|
||||||
@ -163,7 +168,7 @@ impl Surface {
|
|||||||
&self,
|
&self,
|
||||||
adapter: &Adapter<A>,
|
adapter: &Adapter<A>,
|
||||||
) -> Result<hal::SurfaceCapabilities, GetSurfaceSupportError> {
|
) -> Result<hal::SurfaceCapabilities, GetSurfaceSupportError> {
|
||||||
let suf = A::get_surface(self).ok_or(GetSurfaceSupportError::Unsupported)?;
|
let suf = A::surface_as_hal(self).ok_or(GetSurfaceSupportError::Unsupported)?;
|
||||||
profiling::scope!("surface_capabilities");
|
profiling::scope!("surface_capabilities");
|
||||||
let caps = unsafe {
|
let caps = unsafe {
|
||||||
adapter
|
adapter
|
||||||
@ -203,7 +208,7 @@ impl<A: HalApi> Adapter<A> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_surface_supported(&self, surface: &Surface) -> bool {
|
pub fn is_surface_supported(&self, surface: &Surface) -> bool {
|
||||||
let suf = A::get_surface(surface);
|
let suf = A::surface_as_hal(surface);
|
||||||
|
|
||||||
// If get_surface returns None, then the API does not advertise support for the surface.
|
// If get_surface returns None, then the API does not advertise support for the surface.
|
||||||
//
|
//
|
||||||
@ -461,13 +466,25 @@ pub enum RequestAdapterError {
|
|||||||
#[derive(Clone, Debug, Error)]
|
#[derive(Clone, Debug, Error)]
|
||||||
#[non_exhaustive]
|
#[non_exhaustive]
|
||||||
pub enum CreateSurfaceError {
|
pub enum CreateSurfaceError {
|
||||||
#[error("No backend is available")]
|
#[error("The backend {0} was not enabled on the instance.")]
|
||||||
NoSupportedBackend,
|
BackendNotEnabled(Backend),
|
||||||
#[error(transparent)]
|
#[error("Failed to create surface for any enabled backend: {0:?}")]
|
||||||
InstanceError(#[from] hal::InstanceError),
|
FailedToCreateSurfaceForAnyBackend(HashMap<Backend, hal::InstanceError>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Global {
|
impl Global {
|
||||||
|
/// Creates a new surface targeting the given display/window handles.
|
||||||
|
///
|
||||||
|
/// Internally attempts to create hal surfaces for all enabled backends.
|
||||||
|
///
|
||||||
|
/// Fails only if creation for surfaces for all enabled backends fails in which case
|
||||||
|
/// the error for each enabled backend is listed.
|
||||||
|
/// Vice versa, if creation for any backend succeeds, success is returned.
|
||||||
|
/// Surface creation errors are logged to the debug log in any case.
|
||||||
|
///
|
||||||
|
/// id_in:
|
||||||
|
/// - If `Some`, the id to assign to the surface. A new one will be generated otherwise.
|
||||||
|
///
|
||||||
/// # Safety
|
/// # Safety
|
||||||
///
|
///
|
||||||
/// - `display_handle` must be a valid object to create a surface upon.
|
/// - `display_handle` must be a valid object to create a surface upon.
|
||||||
@ -483,51 +500,86 @@ impl Global {
|
|||||||
profiling::scope!("Instance::create_surface");
|
profiling::scope!("Instance::create_surface");
|
||||||
|
|
||||||
fn init<A: HalApi>(
|
fn init<A: HalApi>(
|
||||||
|
errors: &mut HashMap<Backend, hal::InstanceError>,
|
||||||
|
any_created: &mut bool,
|
||||||
|
backend: Backend,
|
||||||
inst: &Option<A::Instance>,
|
inst: &Option<A::Instance>,
|
||||||
display_handle: raw_window_handle::RawDisplayHandle,
|
display_handle: raw_window_handle::RawDisplayHandle,
|
||||||
window_handle: raw_window_handle::RawWindowHandle,
|
window_handle: raw_window_handle::RawWindowHandle,
|
||||||
) -> Option<Result<AnySurface, hal::InstanceError>> {
|
) -> Option<HalSurface<A>> {
|
||||||
inst.as_ref().map(|inst| unsafe {
|
inst.as_ref().and_then(|inst| {
|
||||||
match inst.create_surface(display_handle, window_handle) {
|
match unsafe { inst.create_surface(display_handle, window_handle) } {
|
||||||
Ok(raw) => Ok(AnySurface::new::<A>(raw)),
|
Ok(raw) => {
|
||||||
Err(e) => Err(e),
|
*any_created = true;
|
||||||
|
Some(raw)
|
||||||
|
}
|
||||||
|
Err(err) => {
|
||||||
|
log::debug!(
|
||||||
|
"Instance::create_surface: failed to create surface for {:?}: {:?}",
|
||||||
|
backend,
|
||||||
|
err
|
||||||
|
);
|
||||||
|
errors.insert(backend, err);
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut hal_surface: Option<Result<AnySurface, hal::InstanceError>> = None;
|
let mut errors = HashMap::default();
|
||||||
|
let mut any_created = false;
|
||||||
#[cfg(vulkan)]
|
|
||||||
if hal_surface.is_none() {
|
|
||||||
hal_surface =
|
|
||||||
init::<hal::api::Vulkan>(&self.instance.vulkan, display_handle, window_handle);
|
|
||||||
}
|
|
||||||
#[cfg(metal)]
|
|
||||||
if hal_surface.is_none() {
|
|
||||||
hal_surface =
|
|
||||||
init::<hal::api::Metal>(&self.instance.metal, display_handle, window_handle);
|
|
||||||
}
|
|
||||||
#[cfg(dx12)]
|
|
||||||
if hal_surface.is_none() {
|
|
||||||
hal_surface =
|
|
||||||
init::<hal::api::Dx12>(&self.instance.dx12, display_handle, window_handle);
|
|
||||||
}
|
|
||||||
#[cfg(gles)]
|
|
||||||
if hal_surface.is_none() {
|
|
||||||
hal_surface = init::<hal::api::Gles>(&self.instance.gl, display_handle, window_handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
let hal_surface = hal_surface.ok_or(CreateSurfaceError::NoSupportedBackend)??;
|
|
||||||
|
|
||||||
let surface = Surface {
|
let surface = Surface {
|
||||||
presentation: Mutex::new(None),
|
presentation: Mutex::new(None),
|
||||||
info: ResourceInfo::new("<Surface>", None),
|
info: ResourceInfo::new("<Surface>", None),
|
||||||
raw: hal_surface,
|
|
||||||
|
#[cfg(vulkan)]
|
||||||
|
vulkan: init::<hal::api::Vulkan>(
|
||||||
|
&mut errors,
|
||||||
|
&mut any_created,
|
||||||
|
Backend::Vulkan,
|
||||||
|
&self.instance.vulkan,
|
||||||
|
display_handle,
|
||||||
|
window_handle,
|
||||||
|
),
|
||||||
|
#[cfg(metal)]
|
||||||
|
metal: init::<hal::api::Metal>(
|
||||||
|
&mut errors,
|
||||||
|
&mut any_created,
|
||||||
|
Backend::Metal,
|
||||||
|
&self.instance.metal,
|
||||||
|
display_handle,
|
||||||
|
window_handle,
|
||||||
|
),
|
||||||
|
#[cfg(dx12)]
|
||||||
|
dx12: init::<hal::api::Dx12>(
|
||||||
|
&mut errors,
|
||||||
|
&mut any_created,
|
||||||
|
Backend::Dx12,
|
||||||
|
&self.instance.dx12,
|
||||||
|
display_handle,
|
||||||
|
window_handle,
|
||||||
|
),
|
||||||
|
#[cfg(gles)]
|
||||||
|
gl: init::<hal::api::Gles>(
|
||||||
|
&mut errors,
|
||||||
|
&mut any_created,
|
||||||
|
Backend::Gl,
|
||||||
|
&self.instance.gl,
|
||||||
|
display_handle,
|
||||||
|
window_handle,
|
||||||
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
#[allow(clippy::arc_with_non_send_sync)]
|
if any_created {
|
||||||
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
#[allow(clippy::arc_with_non_send_sync)]
|
||||||
Ok(id)
|
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
||||||
|
Ok(id)
|
||||||
|
} else {
|
||||||
|
Err(CreateSurfaceError::FailedToCreateSurfaceForAnyBackend(
|
||||||
|
errors,
|
||||||
|
))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// # Safety
|
/// # Safety
|
||||||
@ -538,29 +590,57 @@ impl Global {
|
|||||||
&self,
|
&self,
|
||||||
layer: *mut std::ffi::c_void,
|
layer: *mut std::ffi::c_void,
|
||||||
id_in: Option<SurfaceId>,
|
id_in: Option<SurfaceId>,
|
||||||
) -> SurfaceId {
|
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||||
profiling::scope!("Instance::create_surface_metal");
|
profiling::scope!("Instance::create_surface_metal");
|
||||||
|
|
||||||
let surface = Surface {
|
let surface = Surface {
|
||||||
presentation: Mutex::new(None),
|
presentation: Mutex::new(None),
|
||||||
info: ResourceInfo::new("<Surface>", None),
|
info: ResourceInfo::new("<Surface>", None),
|
||||||
raw: {
|
metal: Some(self.instance.metal.as_ref().map_or(
|
||||||
let hal_surface = self
|
Err(CreateSurfaceError::BackendNotEnabled(Backend::Metal)),
|
||||||
.instance
|
|inst| {
|
||||||
.metal
|
// we don't want to link to metal-rs for this
|
||||||
.as_ref()
|
#[allow(clippy::transmute_ptr_to_ref)]
|
||||||
.map(|inst| {
|
Ok(inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) }))
|
||||||
// we don't want to link to metal-rs for this
|
},
|
||||||
#[allow(clippy::transmute_ptr_to_ref)]
|
)?),
|
||||||
inst.create_surface_from_layer(unsafe { std::mem::transmute(layer) })
|
#[cfg(dx12)]
|
||||||
})
|
dx12: None,
|
||||||
.unwrap();
|
#[cfg(vulkan)]
|
||||||
AnySurface::new::<hal::api::Metal>(hal_surface)
|
vulkan: None,
|
||||||
},
|
#[cfg(gles)]
|
||||||
|
gl: None,
|
||||||
};
|
};
|
||||||
|
|
||||||
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
||||||
id
|
Ok(id)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(dx12)]
|
||||||
|
fn instance_create_surface_dx12(
|
||||||
|
&self,
|
||||||
|
id_in: Option<SurfaceId>,
|
||||||
|
create_surface_func: impl FnOnce(&HalInstance<hal::api::Dx12>) -> HalSurface<hal::api::Dx12>,
|
||||||
|
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||||
|
let surface = Surface {
|
||||||
|
presentation: Mutex::new(None),
|
||||||
|
info: ResourceInfo::new("<Surface>", None),
|
||||||
|
dx12: Some(create_surface_func(
|
||||||
|
self.instance
|
||||||
|
.dx12
|
||||||
|
.as_ref()
|
||||||
|
.ok_or(CreateSurfaceError::BackendNotEnabled(Backend::Dx12))?,
|
||||||
|
)),
|
||||||
|
#[cfg(metal)]
|
||||||
|
metal: None,
|
||||||
|
#[cfg(vulkan)]
|
||||||
|
vulkan: None,
|
||||||
|
#[cfg(gles)]
|
||||||
|
gl: None,
|
||||||
|
};
|
||||||
|
|
||||||
|
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
||||||
|
Ok(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
@ -571,25 +651,11 @@ impl Global {
|
|||||||
&self,
|
&self,
|
||||||
visual: *mut std::ffi::c_void,
|
visual: *mut std::ffi::c_void,
|
||||||
id_in: Option<SurfaceId>,
|
id_in: Option<SurfaceId>,
|
||||||
) -> SurfaceId {
|
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||||
profiling::scope!("Instance::instance_create_surface_from_visual");
|
profiling::scope!("Instance::instance_create_surface_from_visual");
|
||||||
|
self.instance_create_surface_dx12(id_in, |inst| unsafe {
|
||||||
let surface = Surface {
|
inst.create_surface_from_visual(visual as _)
|
||||||
presentation: Mutex::new(None),
|
})
|
||||||
info: ResourceInfo::new("<Surface>", None),
|
|
||||||
raw: {
|
|
||||||
let hal_surface = self
|
|
||||||
.instance
|
|
||||||
.dx12
|
|
||||||
.as_ref()
|
|
||||||
.map(|inst| unsafe { inst.create_surface_from_visual(visual as _) })
|
|
||||||
.unwrap();
|
|
||||||
AnySurface::new::<hal::api::Dx12>(hal_surface)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
@ -600,25 +666,11 @@ impl Global {
|
|||||||
&self,
|
&self,
|
||||||
surface_handle: *mut std::ffi::c_void,
|
surface_handle: *mut std::ffi::c_void,
|
||||||
id_in: Option<SurfaceId>,
|
id_in: Option<SurfaceId>,
|
||||||
) -> SurfaceId {
|
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||||
profiling::scope!("Instance::instance_create_surface_from_surface_handle");
|
profiling::scope!("Instance::instance_create_surface_from_surface_handle");
|
||||||
|
self.instance_create_surface_dx12(id_in, |inst| unsafe {
|
||||||
let surface = Surface {
|
inst.create_surface_from_surface_handle(surface_handle)
|
||||||
presentation: Mutex::new(None),
|
})
|
||||||
info: ResourceInfo::new("<Surface>", None),
|
|
||||||
raw: {
|
|
||||||
let hal_surface = self
|
|
||||||
.instance
|
|
||||||
.dx12
|
|
||||||
.as_ref()
|
|
||||||
.map(|inst| unsafe { inst.create_surface_from_surface_handle(surface_handle) })
|
|
||||||
.unwrap();
|
|
||||||
AnySurface::new::<hal::api::Dx12>(hal_surface)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
@ -629,27 +681,11 @@ impl Global {
|
|||||||
&self,
|
&self,
|
||||||
swap_chain_panel: *mut std::ffi::c_void,
|
swap_chain_panel: *mut std::ffi::c_void,
|
||||||
id_in: Option<SurfaceId>,
|
id_in: Option<SurfaceId>,
|
||||||
) -> SurfaceId {
|
) -> Result<SurfaceId, CreateSurfaceError> {
|
||||||
profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
|
profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel");
|
||||||
|
self.instance_create_surface_dx12(id_in, |inst| unsafe {
|
||||||
let surface = Surface {
|
inst.create_surface_from_swap_chain_panel(swap_chain_panel as _)
|
||||||
presentation: Mutex::new(None),
|
})
|
||||||
info: ResourceInfo::new("<Surface>", None),
|
|
||||||
raw: {
|
|
||||||
let hal_surface = self
|
|
||||||
.instance
|
|
||||||
.dx12
|
|
||||||
.as_ref()
|
|
||||||
.map(|inst| unsafe {
|
|
||||||
inst.create_surface_from_swap_chain_panel(swap_chain_panel as _)
|
|
||||||
})
|
|
||||||
.unwrap();
|
|
||||||
AnySurface::new::<hal::api::Dx12>(hal_surface)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
let (id, _) = self.surfaces.prepare(id_in).assign(Arc::new(surface));
|
|
||||||
id
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn surface_drop(&self, id: SurfaceId) {
|
pub fn surface_drop(&self, id: SurfaceId) {
|
||||||
@ -657,11 +693,15 @@ impl Global {
|
|||||||
|
|
||||||
api_log!("Surface::drop {id:?}");
|
api_log!("Surface::drop {id:?}");
|
||||||
|
|
||||||
fn unconfigure<A: HalApi>(global: &Global, surface: &AnySurface, present: &Presentation) {
|
fn unconfigure<A: HalApi>(
|
||||||
let hub = HalApi::hub(global);
|
global: &Global,
|
||||||
if let Some(hal_surface) = surface.downcast_ref::<A>() {
|
surface: &Option<HalSurface<A>>,
|
||||||
|
present: &Presentation,
|
||||||
|
) {
|
||||||
|
if let Some(surface) = surface {
|
||||||
|
let hub = HalApi::hub(global);
|
||||||
if let Some(device) = present.device.downcast_ref::<A>() {
|
if let Some(device) = present.device.downcast_ref::<A>() {
|
||||||
hub.surface_unconfigure(device, hal_surface);
|
hub.surface_unconfigure(device, surface);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -669,15 +709,16 @@ impl Global {
|
|||||||
let surface = self.surfaces.unregister(id);
|
let surface = self.surfaces.unregister(id);
|
||||||
let surface = Arc::into_inner(surface.unwrap())
|
let surface = Arc::into_inner(surface.unwrap())
|
||||||
.expect("Surface cannot be destroyed because is still in use");
|
.expect("Surface cannot be destroyed because is still in use");
|
||||||
|
|
||||||
if let Some(present) = surface.presentation.lock().take() {
|
if let Some(present) = surface.presentation.lock().take() {
|
||||||
#[cfg(vulkan)]
|
#[cfg(vulkan)]
|
||||||
unconfigure::<hal::api::Vulkan>(self, &surface.raw, &present);
|
unconfigure::<hal::api::Vulkan>(self, &surface.vulkan, &present);
|
||||||
#[cfg(metal)]
|
#[cfg(metal)]
|
||||||
unconfigure::<hal::api::Metal>(self, &surface.raw, &present);
|
unconfigure::<hal::api::Metal>(self, &surface.metal, &present);
|
||||||
#[cfg(dx12)]
|
#[cfg(dx12)]
|
||||||
unconfigure::<hal::api::Dx12>(self, &surface.raw, &present);
|
unconfigure::<hal::api::Dx12>(self, &surface.dx12, &present);
|
||||||
#[cfg(gles)]
|
#[cfg(gles)]
|
||||||
unconfigure::<hal::api::Gles>(self, &surface.raw, &present);
|
unconfigure::<hal::api::Gles>(self, &surface.gl, &present);
|
||||||
}
|
}
|
||||||
self.instance.destroy_surface(surface);
|
self.instance.destroy_surface(surface);
|
||||||
}
|
}
|
||||||
@ -785,7 +826,7 @@ impl Global {
|
|||||||
adapters.retain(|exposed| exposed.info.device_type == wgt::DeviceType::Cpu);
|
adapters.retain(|exposed| exposed.info.device_type == wgt::DeviceType::Cpu);
|
||||||
}
|
}
|
||||||
if let Some(surface) = compatible_surface {
|
if let Some(surface) = compatible_surface {
|
||||||
let surface = &A::get_surface(surface);
|
let surface = &A::surface_as_hal(surface);
|
||||||
adapters.retain(|exposed| unsafe {
|
adapters.retain(|exposed| unsafe {
|
||||||
// If the surface does not exist for this backend,
|
// If the surface does not exist for this backend,
|
||||||
// then the surface is not supported.
|
// then the surface is not supported.
|
||||||
|
@ -50,7 +50,6 @@
|
|||||||
unused_qualifications
|
unused_qualifications
|
||||||
)]
|
)]
|
||||||
|
|
||||||
pub mod any_surface;
|
|
||||||
pub mod binding_model;
|
pub mod binding_model;
|
||||||
pub mod command;
|
pub mod command;
|
||||||
mod conv;
|
mod conv;
|
||||||
|
@ -157,7 +157,7 @@ impl Global {
|
|||||||
#[cfg(not(feature = "trace"))]
|
#[cfg(not(feature = "trace"))]
|
||||||
let _ = device;
|
let _ = device;
|
||||||
|
|
||||||
let suf = A::get_surface(surface.as_ref());
|
let suf = A::surface_as_hal(surface.as_ref());
|
||||||
let (texture_id, status) = match unsafe {
|
let (texture_id, status) = match unsafe {
|
||||||
suf.unwrap()
|
suf.unwrap()
|
||||||
.acquire_texture(Some(std::time::Duration::from_millis(
|
.acquire_texture(Some(std::time::Duration::from_millis(
|
||||||
@ -324,7 +324,7 @@ impl Global {
|
|||||||
.textures
|
.textures
|
||||||
.remove(texture.info.tracker_index());
|
.remove(texture.info.tracker_index());
|
||||||
let mut exclusive_snatch_guard = device.snatchable_lock.write();
|
let mut exclusive_snatch_guard = device.snatchable_lock.write();
|
||||||
let suf = A::get_surface(&surface);
|
let suf = A::surface_as_hal(&surface);
|
||||||
let mut inner = texture.inner_mut(&mut exclusive_snatch_guard);
|
let mut inner = texture.inner_mut(&mut exclusive_snatch_guard);
|
||||||
let inner = inner.as_mut().unwrap();
|
let inner = inner.as_mut().unwrap();
|
||||||
|
|
||||||
@ -418,7 +418,7 @@ impl Global {
|
|||||||
.lock()
|
.lock()
|
||||||
.textures
|
.textures
|
||||||
.remove(texture.info.tracker_index());
|
.remove(texture.info.tracker_index());
|
||||||
let suf = A::get_surface(&surface);
|
let suf = A::surface_as_hal(&surface);
|
||||||
let exclusive_snatch_guard = device.snatchable_lock.write();
|
let exclusive_snatch_guard = device.snatchable_lock.write();
|
||||||
match texture.inner.snatch(exclusive_snatch_guard).unwrap() {
|
match texture.inner.snatch(exclusive_snatch_guard).unwrap() {
|
||||||
resource::TextureInner::Surface { mut raw, parent_id } => {
|
resource::TextureInner::Surface { mut raw, parent_id } => {
|
||||||
|
@ -1023,7 +1023,9 @@ impl Global {
|
|||||||
profiling::scope!("Surface::as_hal");
|
profiling::scope!("Surface::as_hal");
|
||||||
|
|
||||||
let surface = self.surfaces.get(id).ok();
|
let surface = self.surfaces.get(id).ok();
|
||||||
let hal_surface = surface.as_ref().and_then(|surface| A::get_surface(surface));
|
let hal_surface = surface
|
||||||
|
.as_ref()
|
||||||
|
.and_then(|surface| A::surface_as_hal(surface));
|
||||||
|
|
||||||
hal_surface_callback(hal_surface)
|
hal_surface_callback(hal_surface)
|
||||||
}
|
}
|
||||||
|
@ -554,7 +554,7 @@ impl crate::Context for ContextWgpuCore {
|
|||||||
raw_window_handle,
|
raw_window_handle,
|
||||||
} => unsafe {
|
} => unsafe {
|
||||||
self.0
|
self.0
|
||||||
.instance_create_surface(raw_display_handle, raw_window_handle, None)?
|
.instance_create_surface(raw_display_handle, raw_window_handle, None)
|
||||||
},
|
},
|
||||||
|
|
||||||
#[cfg(metal)]
|
#[cfg(metal)]
|
||||||
@ -578,7 +578,7 @@ impl crate::Context for ContextWgpuCore {
|
|||||||
self.0
|
self.0
|
||||||
.instance_create_surface_from_swap_chain_panel(swap_chain_panel, None)
|
.instance_create_surface_from_swap_chain_panel(swap_chain_panel, None)
|
||||||
},
|
},
|
||||||
};
|
}?;
|
||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
id,
|
id,
|
||||||
|
@ -366,9 +366,19 @@ static_assertions::assert_impl_all!(SurfaceConfiguration: Send, Sync);
|
|||||||
/// serves a similar role.
|
/// serves a similar role.
|
||||||
pub struct Surface<'window> {
|
pub struct Surface<'window> {
|
||||||
context: Arc<C>,
|
context: Arc<C>,
|
||||||
_surface: Option<Box<dyn WindowHandle + 'window>>,
|
|
||||||
|
/// Optionally, keep the source of the handle used for the surface alive.
|
||||||
|
///
|
||||||
|
/// This is useful for platforms where the surface is created from a window and the surface
|
||||||
|
/// would become invalid when the window is dropped.
|
||||||
|
_handle_source: Option<Box<dyn WindowHandle + 'window>>,
|
||||||
|
|
||||||
|
/// Wgpu-core surface id.
|
||||||
id: ObjectId,
|
id: ObjectId,
|
||||||
data: Box<Data>,
|
|
||||||
|
/// Additional surface data returned by [`DynContext::instance_create_surface`].
|
||||||
|
surface_data: Box<Data>,
|
||||||
|
|
||||||
// Stores the latest `SurfaceConfiguration` that was set using `Surface::configure`.
|
// Stores the latest `SurfaceConfiguration` that was set using `Surface::configure`.
|
||||||
// It is required to set the attributes of the `SurfaceTexture` in the
|
// It is required to set the attributes of the `SurfaceTexture` in the
|
||||||
// `Surface::get_current_texture` method.
|
// `Surface::get_current_texture` method.
|
||||||
@ -385,15 +395,15 @@ impl<'window> fmt::Debug for Surface<'window> {
|
|||||||
f.debug_struct("Surface")
|
f.debug_struct("Surface")
|
||||||
.field("context", &self.context)
|
.field("context", &self.context)
|
||||||
.field(
|
.field(
|
||||||
"_surface",
|
"_handle_source",
|
||||||
&if self._surface.is_some() {
|
&if self._handle_source.is_some() {
|
||||||
"Some"
|
"Some"
|
||||||
} else {
|
} else {
|
||||||
"None"
|
"None"
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.field("id", &self.id)
|
.field("id", &self.id)
|
||||||
.field("data", &self.data)
|
.field("data", &self.surface_data)
|
||||||
.field("config", &self.config)
|
.field("config", &self.config)
|
||||||
.finish()
|
.finish()
|
||||||
}
|
}
|
||||||
@ -405,7 +415,8 @@ static_assertions::assert_impl_all!(Surface<'_>: Send, Sync);
|
|||||||
impl Drop for Surface<'_> {
|
impl Drop for Surface<'_> {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
if !thread::panicking() {
|
if !thread::panicking() {
|
||||||
self.context.surface_drop(&self.id, self.data.as_ref())
|
self.context
|
||||||
|
.surface_drop(&self.id, self.surface_data.as_ref())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1967,6 +1978,8 @@ impl Instance {
|
|||||||
|
|
||||||
/// Creates a new surface targeting a given window/canvas/surface/etc..
|
/// Creates a new surface targeting a given window/canvas/surface/etc..
|
||||||
///
|
///
|
||||||
|
/// Internally, this creates surfaces for all backends that are enabled for this instance.
|
||||||
|
///
|
||||||
/// See [`SurfaceTarget`] for what targets are supported.
|
/// See [`SurfaceTarget`] for what targets are supported.
|
||||||
/// See [`Instance::create_surface_unsafe`] for surface creation with unsafe target variants.
|
/// See [`Instance::create_surface_unsafe`] for surface creation with unsafe target variants.
|
||||||
///
|
///
|
||||||
@ -1977,7 +1990,7 @@ impl Instance {
|
|||||||
target: impl Into<SurfaceTarget<'window>>,
|
target: impl Into<SurfaceTarget<'window>>,
|
||||||
) -> Result<Surface<'window>, CreateSurfaceError> {
|
) -> Result<Surface<'window>, CreateSurfaceError> {
|
||||||
// Handle origin (i.e. window) to optionally take ownership of to make the surface outlast the window.
|
// Handle origin (i.e. window) to optionally take ownership of to make the surface outlast the window.
|
||||||
let handle_origin;
|
let handle_source;
|
||||||
|
|
||||||
let target = target.into();
|
let target = target.into();
|
||||||
let mut surface = match target {
|
let mut surface = match target {
|
||||||
@ -1987,14 +2000,14 @@ impl Instance {
|
|||||||
inner: CreateSurfaceErrorKind::RawHandle(e),
|
inner: CreateSurfaceErrorKind::RawHandle(e),
|
||||||
})?,
|
})?,
|
||||||
);
|
);
|
||||||
handle_origin = Some(window);
|
handle_source = Some(window);
|
||||||
|
|
||||||
surface
|
surface
|
||||||
}?,
|
}?,
|
||||||
|
|
||||||
#[cfg(any(webgpu, webgl))]
|
#[cfg(any(webgpu, webgl))]
|
||||||
SurfaceTarget::Canvas(canvas) => {
|
SurfaceTarget::Canvas(canvas) => {
|
||||||
handle_origin = None;
|
handle_source = None;
|
||||||
|
|
||||||
let value: &wasm_bindgen::JsValue = &canvas;
|
let value: &wasm_bindgen::JsValue = &canvas;
|
||||||
let obj = std::ptr::NonNull::from(value).cast();
|
let obj = std::ptr::NonNull::from(value).cast();
|
||||||
@ -2013,7 +2026,7 @@ impl Instance {
|
|||||||
|
|
||||||
#[cfg(any(webgpu, webgl))]
|
#[cfg(any(webgpu, webgl))]
|
||||||
SurfaceTarget::OffscreenCanvas(canvas) => {
|
SurfaceTarget::OffscreenCanvas(canvas) => {
|
||||||
handle_origin = None;
|
handle_source = None;
|
||||||
|
|
||||||
let value: &wasm_bindgen::JsValue = &canvas;
|
let value: &wasm_bindgen::JsValue = &canvas;
|
||||||
let obj = std::ptr::NonNull::from(value).cast();
|
let obj = std::ptr::NonNull::from(value).cast();
|
||||||
@ -2032,13 +2045,15 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
surface._surface = handle_origin;
|
surface._handle_source = handle_source;
|
||||||
|
|
||||||
Ok(surface)
|
Ok(surface)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new surface targeting a given window/canvas/surface/etc. using an unsafe target.
|
/// Creates a new surface targeting a given window/canvas/surface/etc. using an unsafe target.
|
||||||
///
|
///
|
||||||
|
/// Internally, this creates surfaces for all backends that are enabled for this instance.
|
||||||
|
///
|
||||||
/// See [`SurfaceTargetUnsafe`] for what targets are supported.
|
/// See [`SurfaceTargetUnsafe`] for what targets are supported.
|
||||||
/// See [`Instance::create_surface`] for surface creation with safe target variants.
|
/// See [`Instance::create_surface`] for surface creation with safe target variants.
|
||||||
///
|
///
|
||||||
@ -2053,9 +2068,9 @@ impl Instance {
|
|||||||
|
|
||||||
Ok(Surface {
|
Ok(Surface {
|
||||||
context: Arc::clone(&self.context),
|
context: Arc::clone(&self.context),
|
||||||
_surface: None,
|
_handle_source: None,
|
||||||
id,
|
id,
|
||||||
data,
|
surface_data: data,
|
||||||
config: Mutex::new(None),
|
config: Mutex::new(None),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2229,7 +2244,7 @@ impl Adapter {
|
|||||||
&self.id,
|
&self.id,
|
||||||
self.data.as_ref(),
|
self.data.as_ref(),
|
||||||
&surface.id,
|
&surface.id,
|
||||||
surface.data.as_ref(),
|
surface.surface_data.as_ref(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4833,7 +4848,7 @@ impl Surface<'_> {
|
|||||||
DynContext::surface_get_capabilities(
|
DynContext::surface_get_capabilities(
|
||||||
&*self.context,
|
&*self.context,
|
||||||
&self.id,
|
&self.id,
|
||||||
self.data.as_ref(),
|
self.surface_data.as_ref(),
|
||||||
&adapter.id,
|
&adapter.id,
|
||||||
adapter.data.as_ref(),
|
adapter.data.as_ref(),
|
||||||
)
|
)
|
||||||
@ -4872,7 +4887,7 @@ impl Surface<'_> {
|
|||||||
DynContext::surface_configure(
|
DynContext::surface_configure(
|
||||||
&*self.context,
|
&*self.context,
|
||||||
&self.id,
|
&self.id,
|
||||||
self.data.as_ref(),
|
self.surface_data.as_ref(),
|
||||||
&device.id,
|
&device.id,
|
||||||
device.data.as_ref(),
|
device.data.as_ref(),
|
||||||
config,
|
config,
|
||||||
@ -4891,8 +4906,11 @@ impl Surface<'_> {
|
|||||||
/// If a SurfaceTexture referencing this surface is alive when the swapchain is recreated,
|
/// If a SurfaceTexture referencing this surface is alive when the swapchain is recreated,
|
||||||
/// recreating the swapchain will panic.
|
/// recreating the swapchain will panic.
|
||||||
pub fn get_current_texture(&self) -> Result<SurfaceTexture, SurfaceError> {
|
pub fn get_current_texture(&self) -> Result<SurfaceTexture, SurfaceError> {
|
||||||
let (texture_id, texture_data, status, detail) =
|
let (texture_id, texture_data, status, detail) = DynContext::surface_get_current_texture(
|
||||||
DynContext::surface_get_current_texture(&*self.context, &self.id, self.data.as_ref());
|
&*self.context,
|
||||||
|
&self.id,
|
||||||
|
self.surface_data.as_ref(),
|
||||||
|
);
|
||||||
|
|
||||||
let suboptimal = match status {
|
let suboptimal = match status {
|
||||||
SurfaceStatus::Good => false,
|
SurfaceStatus::Good => false,
|
||||||
@ -4955,7 +4973,7 @@ impl Surface<'_> {
|
|||||||
.downcast_ref::<crate::backend::ContextWgpuCore>()
|
.downcast_ref::<crate::backend::ContextWgpuCore>()
|
||||||
.map(|ctx| unsafe {
|
.map(|ctx| unsafe {
|
||||||
ctx.surface_as_hal::<A, F, R>(
|
ctx.surface_as_hal::<A, F, R>(
|
||||||
self.data.downcast_ref().unwrap(),
|
self.surface_data.downcast_ref().unwrap(),
|
||||||
hal_surface_callback,
|
hal_surface_callback,
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user