mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-12-08 21:26:17 +00:00
Lazy-load the dcomp library (#8216)
This commit is contained in:
parent
04a3401638
commit
aee8cd1650
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -5126,6 +5126,7 @@ dependencies = [
|
|||||||
"naga",
|
"naga",
|
||||||
"ndk-sys 0.6.0+11769913",
|
"ndk-sys 0.6.0+11769913",
|
||||||
"objc",
|
"objc",
|
||||||
|
"once_cell",
|
||||||
"ordered-float 5.0.0",
|
"ordered-float 5.0.0",
|
||||||
"parking_lot",
|
"parking_lot",
|
||||||
"portable-atomic",
|
"portable-atomic",
|
||||||
|
|||||||
@ -136,6 +136,7 @@ dx12 = [
|
|||||||
"dep:libloading",
|
"dep:libloading",
|
||||||
"dep:log",
|
"dep:log",
|
||||||
"dep:ordered-float",
|
"dep:ordered-float",
|
||||||
|
"dep:once_cell",
|
||||||
"dep:parking_lot",
|
"dep:parking_lot",
|
||||||
"dep:profiling",
|
"dep:profiling",
|
||||||
"dep:range-alloc",
|
"dep:range-alloc",
|
||||||
@ -258,6 +259,7 @@ windows-core = { workspace = true, optional = true }
|
|||||||
bit-set = { workspace = true, optional = true }
|
bit-set = { workspace = true, optional = true }
|
||||||
range-alloc = { workspace = true, optional = true }
|
range-alloc = { workspace = true, optional = true }
|
||||||
gpu-allocator = { workspace = true, optional = true }
|
gpu-allocator = { workspace = true, optional = true }
|
||||||
|
once_cell = { workspace = true, optional = true }
|
||||||
# backend: GLES
|
# backend: GLES
|
||||||
glutin_wgl_sys = { workspace = true, optional = true }
|
glutin_wgl_sys = { workspace = true, optional = true }
|
||||||
|
|
||||||
|
|||||||
@ -17,7 +17,7 @@ use crate::{
|
|||||||
self,
|
self,
|
||||||
dxgi::{factory::DxgiAdapter, result::HResult},
|
dxgi::{factory::DxgiAdapter, result::HResult},
|
||||||
},
|
},
|
||||||
dx12::{shader_compilation, SurfaceTarget},
|
dx12::{dcomp::DCompLib, shader_compilation, SurfaceTarget},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl Drop for super::Adapter {
|
impl Drop for super::Adapter {
|
||||||
@ -55,6 +55,7 @@ impl super::Adapter {
|
|||||||
pub(super) fn expose(
|
pub(super) fn expose(
|
||||||
adapter: DxgiAdapter,
|
adapter: DxgiAdapter,
|
||||||
library: &Arc<D3D12Lib>,
|
library: &Arc<D3D12Lib>,
|
||||||
|
dcomp_lib: &Arc<DCompLib>,
|
||||||
instance_flags: wgt::InstanceFlags,
|
instance_flags: wgt::InstanceFlags,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
@ -559,6 +560,7 @@ impl super::Adapter {
|
|||||||
raw: adapter,
|
raw: adapter,
|
||||||
device,
|
device,
|
||||||
library: Arc::clone(library),
|
library: Arc::clone(library),
|
||||||
|
dcomp_lib: Arc::clone(dcomp_lib),
|
||||||
private_caps,
|
private_caps,
|
||||||
presentation_timer,
|
presentation_timer,
|
||||||
workarounds,
|
workarounds,
|
||||||
@ -726,6 +728,7 @@ impl crate::Adapter for super::Adapter {
|
|||||||
memory_hints,
|
memory_hints,
|
||||||
self.private_caps,
|
self.private_caps,
|
||||||
&self.library,
|
&self.library,
|
||||||
|
&self.dcomp_lib,
|
||||||
self.memory_budget_thresholds,
|
self.memory_budget_thresholds,
|
||||||
self.compiler_container.clone(),
|
self.compiler_container.clone(),
|
||||||
self.options.clone(),
|
self.options.clone(),
|
||||||
|
|||||||
@ -1,4 +1,65 @@
|
|||||||
|
use alloc::sync::Arc;
|
||||||
|
use core::{ffi, ptr};
|
||||||
|
|
||||||
|
use once_cell::sync::Lazy;
|
||||||
use windows::Win32::{Foundation::HWND, Graphics::DirectComposition};
|
use windows::Win32::{Foundation::HWND, Graphics::DirectComposition};
|
||||||
|
use windows_core::Interface;
|
||||||
|
|
||||||
|
use super::DynLib;
|
||||||
|
|
||||||
|
// Lazy-loaded DirectComposition library
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub(crate) struct DCompLib {
|
||||||
|
lib: Lazy<Result<DynLib, crate::SurfaceError>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DCompLib {
|
||||||
|
pub(crate) fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
lib: Lazy::new(|| unsafe {
|
||||||
|
DynLib::new("dcomp.dll").map_err(|err| {
|
||||||
|
log::error!("Error loading dcomp.dll: {err}");
|
||||||
|
crate::SurfaceError::Other("Error loading dcomp.dll")
|
||||||
|
})
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lib(&self) -> Result<&DynLib, crate::SurfaceError> {
|
||||||
|
match self.lib.as_ref() {
|
||||||
|
Ok(lib) => Ok(lib),
|
||||||
|
Err(err) => Err(err.clone()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn create_device(
|
||||||
|
&self,
|
||||||
|
) -> Result<DirectComposition::IDCompositionDevice, crate::SurfaceError> {
|
||||||
|
let lib = self.get_lib()?;
|
||||||
|
|
||||||
|
// Calls windows::Win32::Graphics::DirectComposition::DCompositionCreateDevice2 on dcomp.dll
|
||||||
|
type Fun = extern "system" fn(
|
||||||
|
pdxdevice: *mut ffi::c_void,
|
||||||
|
riid: *const windows_core::GUID,
|
||||||
|
ppdcompdevice: *mut *mut ffi::c_void,
|
||||||
|
) -> windows_core::HRESULT;
|
||||||
|
let func: libloading::Symbol<Fun> =
|
||||||
|
unsafe { lib.get(c"DCompositionCreateDevice2".to_bytes()) }?;
|
||||||
|
|
||||||
|
let mut res: Option<DirectComposition::IDCompositionDevice> = None;
|
||||||
|
|
||||||
|
(func)(
|
||||||
|
ptr::null_mut(),
|
||||||
|
&DirectComposition::IDCompositionDevice::IID,
|
||||||
|
<*mut _>::cast(&mut res),
|
||||||
|
)
|
||||||
|
.map(|| res.unwrap())
|
||||||
|
.map_err(|err| {
|
||||||
|
log::error!("DirectComposition::DCompositionCreateDevice2 failed: {err}");
|
||||||
|
crate::SurfaceError::Other("DirectComposition::DCompositionCreateDevice2")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct DCompState {
|
pub struct DCompState {
|
||||||
@ -10,10 +71,11 @@ impl DCompState {
|
|||||||
/// If the device is already initialized, it will return the existing state.
|
/// If the device is already initialized, it will return the existing state.
|
||||||
pub unsafe fn get_or_init(
|
pub unsafe fn get_or_init(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
lib: &Arc<DCompLib>,
|
||||||
hwnd: &HWND,
|
hwnd: &HWND,
|
||||||
) -> Result<&mut InnerState, crate::SurfaceError> {
|
) -> Result<&mut InnerState, crate::SurfaceError> {
|
||||||
if self.inner.is_none() {
|
if self.inner.is_none() {
|
||||||
self.inner = Some(unsafe { InnerState::init(hwnd) }?);
|
self.inner = Some(unsafe { InnerState::init(lib, hwnd) }?);
|
||||||
}
|
}
|
||||||
Ok(self.inner.as_mut().unwrap())
|
Ok(self.inner.as_mut().unwrap())
|
||||||
}
|
}
|
||||||
@ -28,14 +90,9 @@ pub struct InnerState {
|
|||||||
|
|
||||||
impl InnerState {
|
impl InnerState {
|
||||||
/// Creates a DirectComposition device and a target for the given window handle.
|
/// Creates a DirectComposition device and a target for the given window handle.
|
||||||
pub unsafe fn init(hwnd: &HWND) -> Result<Self, crate::SurfaceError> {
|
pub unsafe fn init(lib: &Arc<DCompLib>, hwnd: &HWND) -> Result<Self, crate::SurfaceError> {
|
||||||
profiling::scope!("DCompState::init");
|
profiling::scope!("DCompState::init");
|
||||||
let dcomp_device: DirectComposition::IDCompositionDevice = {
|
let dcomp_device = lib.create_device()?;
|
||||||
unsafe { DirectComposition::DCompositionCreateDevice2(None) }.map_err(|err| {
|
|
||||||
log::error!("DirectComposition::DCompositionCreateDevice failed: {err}");
|
|
||||||
crate::SurfaceError::Other("DirectComposition::DCompositionCreateDevice")
|
|
||||||
})?
|
|
||||||
};
|
|
||||||
|
|
||||||
let target = unsafe { dcomp_device.CreateTargetForHwnd(*hwnd, false) }.map_err(|err| {
|
let target = unsafe { dcomp_device.CreateTargetForHwnd(*hwnd, false) }.map_err(|err| {
|
||||||
log::error!("IDCompositionDevice::CreateTargetForHwnd failed: {err}");
|
log::error!("IDCompositionDevice::CreateTargetForHwnd failed: {err}");
|
||||||
|
|||||||
@ -26,7 +26,7 @@ use crate::{
|
|||||||
dxgi::{name::ObjectExt, result::HResult},
|
dxgi::{name::ObjectExt, result::HResult},
|
||||||
},
|
},
|
||||||
dx12::{
|
dx12::{
|
||||||
borrow_optional_interface_temporarily, shader_compilation, suballocation,
|
borrow_optional_interface_temporarily, shader_compilation, suballocation, DCompLib,
|
||||||
DynamicStorageBufferOffsets, Event, ShaderCacheKey, ShaderCacheValue,
|
DynamicStorageBufferOffsets, Event, ShaderCacheKey, ShaderCacheValue,
|
||||||
},
|
},
|
||||||
AccelerationStructureEntries, TlasInstance,
|
AccelerationStructureEntries, TlasInstance,
|
||||||
@ -46,6 +46,7 @@ impl super::Device {
|
|||||||
memory_hints: &wgt::MemoryHints,
|
memory_hints: &wgt::MemoryHints,
|
||||||
private_caps: super::PrivateCapabilities,
|
private_caps: super::PrivateCapabilities,
|
||||||
library: &Arc<D3D12Lib>,
|
library: &Arc<D3D12Lib>,
|
||||||
|
dcomp_lib: &Arc<DCompLib>,
|
||||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||||
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||||
backend_options: wgt::Dx12BackendOptions,
|
backend_options: wgt::Dx12BackendOptions,
|
||||||
@ -201,6 +202,7 @@ impl super::Device {
|
|||||||
)),
|
)),
|
||||||
options: backend_options,
|
options: backend_options,
|
||||||
library: Arc::clone(library),
|
library: Arc::clone(library),
|
||||||
|
dcomp_lib: Arc::clone(dcomp_lib),
|
||||||
#[cfg(feature = "renderdoc")]
|
#[cfg(feature = "renderdoc")]
|
||||||
render_doc: Default::default(),
|
render_doc: Default::default(),
|
||||||
null_rtv_handle,
|
null_rtv_handle,
|
||||||
|
|||||||
@ -12,7 +12,7 @@ use windows::{
|
|||||||
use super::SurfaceTarget;
|
use super::SurfaceTarget;
|
||||||
use crate::{
|
use crate::{
|
||||||
auxil,
|
auxil,
|
||||||
dx12::{shader_compilation::CompilerContainer, D3D12Lib},
|
dx12::{shader_compilation::CompilerContainer, D3D12Lib, DCompLib},
|
||||||
};
|
};
|
||||||
|
|
||||||
impl crate::Instance for super::Instance {
|
impl crate::Instance for super::Instance {
|
||||||
@ -104,6 +104,7 @@ impl crate::Instance for super::Instance {
|
|||||||
factory,
|
factory,
|
||||||
factory_media,
|
factory_media,
|
||||||
library: Arc::new(lib_main),
|
library: Arc::new(lib_main),
|
||||||
|
dcomp_lib: Arc::new(DCompLib::new()),
|
||||||
presentation_system: desc.backend_options.dx12.presentation_system,
|
presentation_system: desc.backend_options.dx12.presentation_system,
|
||||||
_lib_dxgi: lib_dxgi,
|
_lib_dxgi: lib_dxgi,
|
||||||
supports_allow_tearing,
|
supports_allow_tearing,
|
||||||
@ -158,6 +159,7 @@ impl crate::Instance for super::Instance {
|
|||||||
super::Adapter::expose(
|
super::Adapter::expose(
|
||||||
raw,
|
raw,
|
||||||
&self.library,
|
&self.library,
|
||||||
|
&self.dcomp_lib,
|
||||||
self.flags,
|
self.flags,
|
||||||
self.memory_budget_thresholds,
|
self.memory_budget_thresholds,
|
||||||
self.compiler_container.clone(),
|
self.compiler_container.clone(),
|
||||||
|
|||||||
@ -101,6 +101,7 @@ use windows::{
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use self::dcomp::DCompLib;
|
||||||
use crate::auxil::{
|
use crate::auxil::{
|
||||||
self,
|
self,
|
||||||
dxgi::{
|
dxgi::{
|
||||||
@ -460,6 +461,7 @@ pub struct Instance {
|
|||||||
factory: DxgiFactory,
|
factory: DxgiFactory,
|
||||||
factory_media: Option<Dxgi::IDXGIFactoryMedia>,
|
factory_media: Option<Dxgi::IDXGIFactoryMedia>,
|
||||||
library: Arc<D3D12Lib>,
|
library: Arc<D3D12Lib>,
|
||||||
|
dcomp_lib: Arc<DCompLib>,
|
||||||
supports_allow_tearing: bool,
|
supports_allow_tearing: bool,
|
||||||
presentation_system: wgt::Dx12SwapchainKind,
|
presentation_system: wgt::Dx12SwapchainKind,
|
||||||
_lib_dxgi: DxgiLib,
|
_lib_dxgi: DxgiLib,
|
||||||
@ -612,6 +614,7 @@ pub struct Adapter {
|
|||||||
raw: DxgiAdapter,
|
raw: DxgiAdapter,
|
||||||
device: Direct3D12::ID3D12Device,
|
device: Direct3D12::ID3D12Device,
|
||||||
library: Arc<D3D12Lib>,
|
library: Arc<D3D12Lib>,
|
||||||
|
dcomp_lib: Arc<DCompLib>,
|
||||||
private_caps: PrivateCapabilities,
|
private_caps: PrivateCapabilities,
|
||||||
presentation_timer: auxil::dxgi::time::PresentationTimer,
|
presentation_timer: auxil::dxgi::time::PresentationTimer,
|
||||||
// Note: this isn't used right now, but we'll need it later.
|
// Note: this isn't used right now, but we'll need it later.
|
||||||
@ -685,6 +688,7 @@ pub struct Device {
|
|||||||
srv_uav_pool: Mutex<descriptor::CpuPool>,
|
srv_uav_pool: Mutex<descriptor::CpuPool>,
|
||||||
// library
|
// library
|
||||||
library: Arc<D3D12Lib>,
|
library: Arc<D3D12Lib>,
|
||||||
|
dcomp_lib: Arc<DCompLib>,
|
||||||
#[cfg(feature = "renderdoc")]
|
#[cfg(feature = "renderdoc")]
|
||||||
render_doc: auxil::renderdoc::RenderDoc,
|
render_doc: auxil::renderdoc::RenderDoc,
|
||||||
null_rtv_handle: descriptor::Handle,
|
null_rtv_handle: descriptor::Handle,
|
||||||
@ -1358,7 +1362,8 @@ impl crate::Surface for Surface {
|
|||||||
dcomp_state,
|
dcomp_state,
|
||||||
} => {
|
} => {
|
||||||
let mut dcomp_state = dcomp_state.lock();
|
let mut dcomp_state = dcomp_state.lock();
|
||||||
let dcomp_state = unsafe { dcomp_state.get_or_init(handle) }?;
|
let dcomp_state =
|
||||||
|
unsafe { dcomp_state.get_or_init(&device.dcomp_lib, handle) }?;
|
||||||
// Set the new swap chain as the content for the backing visual
|
// Set the new swap chain as the content for the backing visual
|
||||||
// and commit the changes to the composition visual tree.
|
// and commit the changes to the composition visual tree.
|
||||||
{
|
{
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user