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",
|
||||
"ndk-sys 0.6.0+11769913",
|
||||
"objc",
|
||||
"once_cell",
|
||||
"ordered-float 5.0.0",
|
||||
"parking_lot",
|
||||
"portable-atomic",
|
||||
|
||||
@ -136,6 +136,7 @@ dx12 = [
|
||||
"dep:libloading",
|
||||
"dep:log",
|
||||
"dep:ordered-float",
|
||||
"dep:once_cell",
|
||||
"dep:parking_lot",
|
||||
"dep:profiling",
|
||||
"dep:range-alloc",
|
||||
@ -258,6 +259,7 @@ windows-core = { workspace = true, optional = true }
|
||||
bit-set = { workspace = true, optional = true }
|
||||
range-alloc = { workspace = true, optional = true }
|
||||
gpu-allocator = { workspace = true, optional = true }
|
||||
once_cell = { workspace = true, optional = true }
|
||||
# backend: GLES
|
||||
glutin_wgl_sys = { workspace = true, optional = true }
|
||||
|
||||
|
||||
@ -17,7 +17,7 @@ use crate::{
|
||||
self,
|
||||
dxgi::{factory::DxgiAdapter, result::HResult},
|
||||
},
|
||||
dx12::{shader_compilation, SurfaceTarget},
|
||||
dx12::{dcomp::DCompLib, shader_compilation, SurfaceTarget},
|
||||
};
|
||||
|
||||
impl Drop for super::Adapter {
|
||||
@ -55,6 +55,7 @@ impl super::Adapter {
|
||||
pub(super) fn expose(
|
||||
adapter: DxgiAdapter,
|
||||
library: &Arc<D3D12Lib>,
|
||||
dcomp_lib: &Arc<DCompLib>,
|
||||
instance_flags: wgt::InstanceFlags,
|
||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||
@ -559,6 +560,7 @@ impl super::Adapter {
|
||||
raw: adapter,
|
||||
device,
|
||||
library: Arc::clone(library),
|
||||
dcomp_lib: Arc::clone(dcomp_lib),
|
||||
private_caps,
|
||||
presentation_timer,
|
||||
workarounds,
|
||||
@ -726,6 +728,7 @@ impl crate::Adapter for super::Adapter {
|
||||
memory_hints,
|
||||
self.private_caps,
|
||||
&self.library,
|
||||
&self.dcomp_lib,
|
||||
self.memory_budget_thresholds,
|
||||
self.compiler_container.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_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)]
|
||||
pub struct DCompState {
|
||||
@ -10,10 +71,11 @@ impl DCompState {
|
||||
/// If the device is already initialized, it will return the existing state.
|
||||
pub unsafe fn get_or_init(
|
||||
&mut self,
|
||||
lib: &Arc<DCompLib>,
|
||||
hwnd: &HWND,
|
||||
) -> Result<&mut InnerState, crate::SurfaceError> {
|
||||
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())
|
||||
}
|
||||
@ -28,14 +90,9 @@ pub struct InnerState {
|
||||
|
||||
impl InnerState {
|
||||
/// 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");
|
||||
let dcomp_device: DirectComposition::IDCompositionDevice = {
|
||||
unsafe { DirectComposition::DCompositionCreateDevice2(None) }.map_err(|err| {
|
||||
log::error!("DirectComposition::DCompositionCreateDevice failed: {err}");
|
||||
crate::SurfaceError::Other("DirectComposition::DCompositionCreateDevice")
|
||||
})?
|
||||
};
|
||||
let dcomp_device = lib.create_device()?;
|
||||
|
||||
let target = unsafe { dcomp_device.CreateTargetForHwnd(*hwnd, false) }.map_err(|err| {
|
||||
log::error!("IDCompositionDevice::CreateTargetForHwnd failed: {err}");
|
||||
|
||||
@ -26,7 +26,7 @@ use crate::{
|
||||
dxgi::{name::ObjectExt, result::HResult},
|
||||
},
|
||||
dx12::{
|
||||
borrow_optional_interface_temporarily, shader_compilation, suballocation,
|
||||
borrow_optional_interface_temporarily, shader_compilation, suballocation, DCompLib,
|
||||
DynamicStorageBufferOffsets, Event, ShaderCacheKey, ShaderCacheValue,
|
||||
},
|
||||
AccelerationStructureEntries, TlasInstance,
|
||||
@ -46,6 +46,7 @@ impl super::Device {
|
||||
memory_hints: &wgt::MemoryHints,
|
||||
private_caps: super::PrivateCapabilities,
|
||||
library: &Arc<D3D12Lib>,
|
||||
dcomp_lib: &Arc<DCompLib>,
|
||||
memory_budget_thresholds: wgt::MemoryBudgetThresholds,
|
||||
compiler_container: Arc<shader_compilation::CompilerContainer>,
|
||||
backend_options: wgt::Dx12BackendOptions,
|
||||
@ -201,6 +202,7 @@ impl super::Device {
|
||||
)),
|
||||
options: backend_options,
|
||||
library: Arc::clone(library),
|
||||
dcomp_lib: Arc::clone(dcomp_lib),
|
||||
#[cfg(feature = "renderdoc")]
|
||||
render_doc: Default::default(),
|
||||
null_rtv_handle,
|
||||
|
||||
@ -12,7 +12,7 @@ use windows::{
|
||||
use super::SurfaceTarget;
|
||||
use crate::{
|
||||
auxil,
|
||||
dx12::{shader_compilation::CompilerContainer, D3D12Lib},
|
||||
dx12::{shader_compilation::CompilerContainer, D3D12Lib, DCompLib},
|
||||
};
|
||||
|
||||
impl crate::Instance for super::Instance {
|
||||
@ -104,6 +104,7 @@ impl crate::Instance for super::Instance {
|
||||
factory,
|
||||
factory_media,
|
||||
library: Arc::new(lib_main),
|
||||
dcomp_lib: Arc::new(DCompLib::new()),
|
||||
presentation_system: desc.backend_options.dx12.presentation_system,
|
||||
_lib_dxgi: lib_dxgi,
|
||||
supports_allow_tearing,
|
||||
@ -158,6 +159,7 @@ impl crate::Instance for super::Instance {
|
||||
super::Adapter::expose(
|
||||
raw,
|
||||
&self.library,
|
||||
&self.dcomp_lib,
|
||||
self.flags,
|
||||
self.memory_budget_thresholds,
|
||||
self.compiler_container.clone(),
|
||||
|
||||
@ -101,6 +101,7 @@ use windows::{
|
||||
},
|
||||
};
|
||||
|
||||
use self::dcomp::DCompLib;
|
||||
use crate::auxil::{
|
||||
self,
|
||||
dxgi::{
|
||||
@ -460,6 +461,7 @@ pub struct Instance {
|
||||
factory: DxgiFactory,
|
||||
factory_media: Option<Dxgi::IDXGIFactoryMedia>,
|
||||
library: Arc<D3D12Lib>,
|
||||
dcomp_lib: Arc<DCompLib>,
|
||||
supports_allow_tearing: bool,
|
||||
presentation_system: wgt::Dx12SwapchainKind,
|
||||
_lib_dxgi: DxgiLib,
|
||||
@ -612,6 +614,7 @@ pub struct Adapter {
|
||||
raw: DxgiAdapter,
|
||||
device: Direct3D12::ID3D12Device,
|
||||
library: Arc<D3D12Lib>,
|
||||
dcomp_lib: Arc<DCompLib>,
|
||||
private_caps: PrivateCapabilities,
|
||||
presentation_timer: auxil::dxgi::time::PresentationTimer,
|
||||
// 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>,
|
||||
// library
|
||||
library: Arc<D3D12Lib>,
|
||||
dcomp_lib: Arc<DCompLib>,
|
||||
#[cfg(feature = "renderdoc")]
|
||||
render_doc: auxil::renderdoc::RenderDoc,
|
||||
null_rtv_handle: descriptor::Handle,
|
||||
@ -1358,7 +1362,8 @@ impl crate::Surface for Surface {
|
||||
dcomp_state,
|
||||
} => {
|
||||
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
|
||||
// and commit the changes to the composition visual tree.
|
||||
{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user