From ffffc095117133a720a96e2e04f30e252489e973 Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Sat, 30 Sep 2023 23:44:50 -0500 Subject: [PATCH 1/5] Add SwapChainPanel support --- wgpu-core/src/instance.rs | 28 ++++++++++++++++++++++++++++ wgpu-hal/src/dx12/mod.rs | 28 ++++++++++++++++++++++++++-- wgpu-hal/src/dx12/types.rs | 5 +++++ wgpu/src/backend/direct.rs | 15 +++++++++++++++ wgpu/src/lib.rs | 22 ++++++++++++++++++++++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 9fc198373d..7e8265cc45 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -656,6 +656,34 @@ impl Global { id.0 } + #[cfg(all(feature = "dx12", windows))] + /// # Safety + /// + /// The swap_chain_panel must be valid and able to be used to make a swapchain with. + pub unsafe fn instance_create_surface_from_swap_chain_panel( + &self, + swap_chain_panel: *mut std::ffi::c_void, + id_in: Input, + ) -> SurfaceId { + profiling::scope!("Instance::instance_create_surface_from_swap_chain_panel"); + + let surface = Surface { + presentation: None, + #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))] + vulkan: None, + dx12: self.instance.dx12.as_ref().map(|inst| HalSurface { + raw: unsafe { inst.create_surface_from_swap_chain_panel(swap_chain_panel) }, + }), + dx11: None, + #[cfg(feature = "gles")] + gl: None, + }; + + let mut token = Token::root(); + let id = self.surfaces.prepare(id_in).assign(surface, &mut token); + id.0 + } + pub fn surface_drop(&self, id: SurfaceId) { profiling::scope!("Surface::drop"); log::trace!("Surface::drop {id:?}"); diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index a231619512..bb34e842eb 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -124,6 +124,19 @@ impl Instance { swap_chain: None, } } + + pub unsafe fn create_surface_from_swap_chain_panel( + &self, + swap_chain_panel: *mut ISwapChainPanelNative, + ) -> Surface { + Surface { + factory: self.factory.clone(), + factory_media: self.factory_media.clone(), + target: SurfaceTarget::SwapChainPanel(unsafe { d3d12::ComPtr::from_raw(swap_chain_panel) }), + supports_allow_tearing: self.supports_allow_tearing, + swap_chain: None, + } + } } unsafe impl Send for Instance {} @@ -145,6 +158,7 @@ enum SurfaceTarget { WndHandle(windef::HWND), Visual(d3d12::ComPtr), SurfaceHandle(winnt::HANDLE), + SwapChainPanel(d3d12::ComPtr), } pub struct Surface { @@ -666,7 +680,7 @@ impl crate::Surface for Surface { flags, }; let swap_chain1 = match self.target { - SurfaceTarget::Visual(_) => { + SurfaceTarget::Visual(_) | SurfaceTarget::SwapChainPanel(_) => { profiling::scope!("IDXGIFactory4::CreateSwapChainForComposition"); self.factory .unwrap_factory2() @@ -724,6 +738,16 @@ impl crate::Surface for Surface { )); } } + &SurfaceTarget::SwapChainPanel(ref swap_chain_panel) => { + if let Err(err) = + unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_unknown()) }.into_result() + { + log::error!("Unable to SetSwapChain: {}", err); + return Err(crate::SurfaceError::Other( + "ISwapChainPanelNative::SetSwapChain", + )); + } + } } match unsafe { swap_chain1.cast::() }.into_result() { @@ -748,7 +772,7 @@ impl crate::Surface for Surface { ) }; } - SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) => {} + SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) | SurfaceTarget::SwapChainPanel(_) => {} } unsafe { swap_chain.SetMaximumFrameLatency(config.swap_chain_size) }; diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs index dec4e71337..88a9c47d11 100644 --- a/wgpu-hal/src/dx12/types.rs +++ b/wgpu-hal/src/dx12/types.rs @@ -32,3 +32,8 @@ winapi::STRUCT! { BarycentricsSupported: winapi::shared::minwindef::BOOL, } } + +winapi::RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] +interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { + fn SetSwapChain(swapChain: *mut winapi::shared::dxgi::IDXGISwapChain) -> winapi::um::winnt::HRESULT, +}} diff --git a/wgpu/src/backend/direct.rs b/wgpu/src/backend/direct.rs index e8776f881a..bfdd1909ab 100644 --- a/wgpu/src/backend/direct.rs +++ b/wgpu/src/backend/direct.rs @@ -287,6 +287,21 @@ impl Context { } } + #[cfg(target_os = "windows")] + pub unsafe fn create_surface_from_swap_chain_panel( + &self, + swap_chain_panel: *mut std::ffi::c_void, + ) -> Surface { + let id = unsafe { + self.0 + .instance_create_surface_from_swap_chain_panel(swap_chain_panel, ()) + }; + Surface { + id, + configured_device: Mutex::default(), + } + } + fn handle_error( &self, sink_mutex: &Mutex, diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index f5323a6e34..6a17d4e451 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2027,6 +2027,28 @@ impl Instance { } } + /// Creates a surface from `SwapChainPanel`. + /// + /// # Safety + /// + /// - visual must be a valid SwapChainPanel to create a surface upon. + #[cfg(target_os = "windows")] + pub unsafe fn create_surface_from_swap_chain_panel(&self, swap_chain_panel: *mut std::ffi::c_void) -> Surface { + let surface = unsafe { + self.context + .as_any() + .downcast_ref::() + .unwrap() + .create_surface_from_visual(visual) + }; + Surface { + context: Arc::clone(&self.context), + id: ObjectId::from(surface.id()), + data: Box::new(surface), + config: Mutex::new(None), + } + } + /// Creates a surface from a `web_sys::HtmlCanvasElement`. /// /// The `canvas` argument must be a valid `` element to From bbafab91412cba35c8ef7c13574b40be187ded72 Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Thu, 5 Oct 2023 22:56:46 -0500 Subject: [PATCH 2/5] Correct guid --- wgpu-hal/src/dx12/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs index 88a9c47d11..21e58736a5 100644 --- a/wgpu-hal/src/dx12/types.rs +++ b/wgpu-hal/src/dx12/types.rs @@ -33,7 +33,7 @@ winapi::STRUCT! { } } -winapi::RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] +winapi::RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { fn SetSwapChain(swapChain: *mut winapi::shared::dxgi::IDXGISwapChain) -> winapi::um::winnt::HRESULT, }} From 5d58db0022b50dfe19f20aa01b2c75c745ca9bf4 Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Sun, 8 Oct 2023 18:21:41 -0500 Subject: [PATCH 3/5] Fix RIDL macro --- wgpu-core/src/instance.rs | 2 +- wgpu-hal/src/dx12/adapter.rs | 2 +- wgpu-hal/src/dx12/mod.rs | 6 +++--- wgpu-hal/src/dx12/types.rs | 15 +++++++++++---- wgpu/src/lib.rs | 2 +- 5 files changed, 17 insertions(+), 10 deletions(-) diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 7e8265cc45..374ea1a15d 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -672,7 +672,7 @@ impl Global { #[cfg(all(feature = "vulkan", not(target_arch = "wasm32")))] vulkan: None, dx12: self.instance.dx12.as_ref().map(|inst| HalSurface { - raw: unsafe { inst.create_surface_from_swap_chain_panel(swap_chain_panel) }, + raw: unsafe { inst.create_surface_from_swap_chain_panel(swap_chain_panel as _) }, }), dx11: None, #[cfg(feature = "gles")] diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 3959deeccd..6f5c11488f 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -580,7 +580,7 @@ impl crate::Adapter for super::Adapter { None } } - SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) => None, + SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) | SurfaceTarget::SwapChainPanel(_)=> None, } }; diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index bb34e842eb..21e9a93bd1 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -127,7 +127,7 @@ impl Instance { pub unsafe fn create_surface_from_swap_chain_panel( &self, - swap_chain_panel: *mut ISwapChainPanelNative, + swap_chain_panel: *mut types::ISwapChainPanelNative, ) -> Surface { Surface { factory: self.factory.clone(), @@ -158,7 +158,7 @@ enum SurfaceTarget { WndHandle(windef::HWND), Visual(d3d12::ComPtr), SurfaceHandle(winnt::HANDLE), - SwapChainPanel(d3d12::ComPtr), + SwapChainPanel(d3d12::ComPtr), } pub struct Surface { @@ -740,7 +740,7 @@ impl crate::Surface for Surface { } &SurfaceTarget::SwapChainPanel(ref swap_chain_panel) => { if let Err(err) = - unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_unknown()) }.into_result() + unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_ptr()) }.into_result() { log::error!("Unable to SetSwapChain: {}", err); return Err(crate::SurfaceError::Other( diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs index 21e58736a5..79ff212e44 100644 --- a/wgpu-hal/src/dx12/types.rs +++ b/wgpu-hal/src/dx12/types.rs @@ -1,6 +1,16 @@ #![allow(non_camel_case_types)] #![allow(non_snake_case)] +// use here so that the recursive RIDL macro can find the crate +use winapi::RIDL; +use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; + +RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] + interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { + fn SetSwapChain(swapChain: *const winapi::shared::dxgi1_2::IDXGISwapChain1,) -> winapi::um::winnt::HRESULT, + }} + + winapi::ENUM! { enum D3D12_VIEW_INSTANCING_TIER { D3D12_VIEW_INSTANCING_TIER_NOT_SUPPORTED = 0, @@ -33,7 +43,4 @@ winapi::STRUCT! { } } -winapi::RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] -interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { - fn SetSwapChain(swapChain: *mut winapi::shared::dxgi::IDXGISwapChain) -> winapi::um::winnt::HRESULT, -}} + diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 6a17d4e451..8e0dd80691 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2039,7 +2039,7 @@ impl Instance { .as_any() .downcast_ref::() .unwrap() - .create_surface_from_visual(visual) + .create_surface_from_swap_chain_panel(swap_chain_panel) }; Surface { context: Arc::clone(&self.context), From a695c881a061c6aa822b4c54d55a10976ae80bd0 Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Sun, 8 Oct 2023 20:13:26 -0500 Subject: [PATCH 4/5] Formatting --- wgpu-hal/src/dx12/adapter.rs | 4 +++- wgpu-hal/src/dx12/mod.rs | 11 ++++++++--- wgpu-hal/src/dx12/types.rs | 13 +++++-------- wgpu/src/lib.rs | 5 ++++- 4 files changed, 20 insertions(+), 13 deletions(-) diff --git a/wgpu-hal/src/dx12/adapter.rs b/wgpu-hal/src/dx12/adapter.rs index 6f5c11488f..269dcd267c 100644 --- a/wgpu-hal/src/dx12/adapter.rs +++ b/wgpu-hal/src/dx12/adapter.rs @@ -580,7 +580,9 @@ impl crate::Adapter for super::Adapter { None } } - SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) | SurfaceTarget::SwapChainPanel(_)=> None, + SurfaceTarget::Visual(_) + | SurfaceTarget::SurfaceHandle(_) + | SurfaceTarget::SwapChainPanel(_) => None, } }; diff --git a/wgpu-hal/src/dx12/mod.rs b/wgpu-hal/src/dx12/mod.rs index 21e9a93bd1..81a06c5140 100644 --- a/wgpu-hal/src/dx12/mod.rs +++ b/wgpu-hal/src/dx12/mod.rs @@ -132,7 +132,9 @@ impl Instance { Surface { factory: self.factory.clone(), factory_media: self.factory_media.clone(), - target: SurfaceTarget::SwapChainPanel(unsafe { d3d12::ComPtr::from_raw(swap_chain_panel) }), + target: SurfaceTarget::SwapChainPanel(unsafe { + d3d12::ComPtr::from_raw(swap_chain_panel) + }), supports_allow_tearing: self.supports_allow_tearing, swap_chain: None, } @@ -740,7 +742,8 @@ impl crate::Surface for Surface { } &SurfaceTarget::SwapChainPanel(ref swap_chain_panel) => { if let Err(err) = - unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_ptr()) }.into_result() + unsafe { swap_chain_panel.SetSwapChain(swap_chain1.as_ptr()) } + .into_result() { log::error!("Unable to SetSwapChain: {}", err); return Err(crate::SurfaceError::Other( @@ -772,7 +775,9 @@ impl crate::Surface for Surface { ) }; } - SurfaceTarget::Visual(_) | SurfaceTarget::SurfaceHandle(_) | SurfaceTarget::SwapChainPanel(_) => {} + SurfaceTarget::Visual(_) + | SurfaceTarget::SurfaceHandle(_) + | SurfaceTarget::SwapChainPanel(_) => {} } unsafe { swap_chain.SetMaximumFrameLatency(config.swap_chain_size) }; diff --git a/wgpu-hal/src/dx12/types.rs b/wgpu-hal/src/dx12/types.rs index 79ff212e44..b4ad38324a 100644 --- a/wgpu-hal/src/dx12/types.rs +++ b/wgpu-hal/src/dx12/types.rs @@ -2,14 +2,13 @@ #![allow(non_snake_case)] // use here so that the recursive RIDL macro can find the crate -use winapi::RIDL; use winapi::um::unknwnbase::{IUnknown, IUnknownVtbl}; +use winapi::RIDL; -RIDL!{#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] - interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { - fn SetSwapChain(swapChain: *const winapi::shared::dxgi1_2::IDXGISwapChain1,) -> winapi::um::winnt::HRESULT, - }} - +RIDL! {#[uuid(0x63aad0b8, 0x7c24, 0x40ff, 0x85, 0xa8, 0x64, 0x0d, 0x94, 0x4c, 0xc3, 0x25)] +interface ISwapChainPanelNative(ISwapChainPanelNativeVtbl): IUnknown(IUnknownVtbl) { + fn SetSwapChain(swapChain: *const winapi::shared::dxgi1_2::IDXGISwapChain1,) -> winapi::um::winnt::HRESULT, +}} winapi::ENUM! { enum D3D12_VIEW_INSTANCING_TIER { @@ -42,5 +41,3 @@ winapi::STRUCT! { BarycentricsSupported: winapi::shared::minwindef::BOOL, } } - - diff --git a/wgpu/src/lib.rs b/wgpu/src/lib.rs index 8e0dd80691..0e6037e493 100644 --- a/wgpu/src/lib.rs +++ b/wgpu/src/lib.rs @@ -2033,7 +2033,10 @@ impl Instance { /// /// - visual must be a valid SwapChainPanel to create a surface upon. #[cfg(target_os = "windows")] - pub unsafe fn create_surface_from_swap_chain_panel(&self, swap_chain_panel: *mut std::ffi::c_void) -> Surface { + pub unsafe fn create_surface_from_swap_chain_panel( + &self, + swap_chain_panel: *mut std::ffi::c_void, + ) -> Surface { let surface = unsafe { self.context .as_any() From e49573c5d1483b7cc33b4a5cb169481f2e666af7 Mon Sep 17 00:00:00 2001 From: Colin Edwards Date: Sun, 8 Oct 2023 20:18:55 -0500 Subject: [PATCH 5/5] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 718c940bc2..d81a9f25db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -96,6 +96,7 @@ By @teoxoy in [#4185](https://github.com/gfx-rs/wgpu/pull/4185) - Add `gles_minor_version` field to `wgpu::InstanceDescriptor`. By @PJB3005 in [#3998](https://github.com/gfx-rs/wgpu/pull/3998) - Re-export Naga. By @exrook in [#4172](https://github.com/gfx-rs/wgpu/pull/4172) +- Add WinUI 3 SwapChainPanel support. By @ddrboxman in [#4191](https://github.com/gfx-rs/wgpu/pull/4191) ### Changes