diff --git a/Cargo.toml b/Cargo.toml index 8865694860..c7e24f2c0b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,9 +9,13 @@ license = "MIT OR Apache-2.0" documentation = "https://docs.rs/d3d12" categories = ["memory-management"] +[features] +libstatic = [] + [dependencies] bitflags = "1" +libloading = { version = "0.5", optional = true } [dependencies.winapi] version = "0.3" -features = ["dxgi1_2","dxgi1_3","dxgi1_4","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","synchapi","winerror"] +features = ["dxgi1_2","dxgi1_3","dxgi1_4","dxgidebug","d3d12","d3d12sdklayers","d3dcommon","d3dcompiler","dxgiformat","synchapi","winerror"] diff --git a/appveyor.yml b/appveyor.yml index 39dc970a9e..f71194b856 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -24,3 +24,6 @@ install: build: false test_script: - cargo check + - cargo check --features libloading + - cargo check --features libstatic + - cargo check --all-features diff --git a/src/debug.rs b/src/debug.rs index f614a27fa7..a5d3d16541 100644 --- a/src/debug.rs +++ b/src/debug.rs @@ -1,15 +1,40 @@ use com::WeakPtr; -use winapi::um::{d3d12, d3d12sdklayers}; -use winapi::Interface; -use D3DResult; +#[cfg(any(feature = "libloading", feature = "libstatic"))] +use winapi::Interface as _; +use winapi::um::d3d12sdklayers; pub type Debug = WeakPtr; -impl Debug { - pub fn get_interface() -> D3DResult { +#[cfg(feature = "libloading")] +impl crate::D3D12Lib { + pub fn get_debug_interface(&self) -> libloading::Result> { + type Fun = extern "system" fn( + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> crate::HRESULT; + let mut debug = Debug::null(); let hr = unsafe { - d3d12::D3D12GetDebugInterface(&d3d12sdklayers::ID3D12Debug::uuidof(), debug.mut_void()) + let func: libloading::Symbol = self.lib.get(b"D3D12GetDebugInterface")?; + func( + &d3d12sdklayers::ID3D12Debug::uuidof(), + debug.mut_void(), + ) + }; + + Ok((debug, hr)) + } +} + +impl Debug { + #[cfg(feature = "libstatic")] + pub fn get_interface() -> crate::D3DResult { + let mut debug = Debug::null(); + let hr = unsafe { + winapi::um::d3d12::D3D12GetDebugInterface( + &d3d12sdklayers::ID3D12Debug::uuidof(), + debug.mut_void(), + ) }; (debug, hr) diff --git a/src/descriptor.rs b/src/descriptor.rs index 9fd1e207e2..3403e359d1 100644 --- a/src/descriptor.rs +++ b/src/descriptor.rs @@ -156,7 +156,6 @@ impl StaticSampler { pub fn new( visibility: ShaderVisibility, binding: Binding, - filter: d3d12::D3D12_FILTER, address_mode: TextureAddressMode, mip_lod_bias: f32, @@ -202,14 +201,57 @@ bitflags! { } pub type RootSignature = WeakPtr; +pub type BlobResult = D3DResult<(Blob, Error)>; + +#[cfg(feature = "libloading")] +impl crate::D3D12Lib { + pub fn serialize_root_signature( + &self, + version: RootSignatureVersion, + parameters: &[RootParameter], + static_samplers: &[StaticSampler], + flags: RootSignatureFlags, + ) -> libloading::Result { + use winapi::um::d3dcommon::ID3DBlob; + type Fun = extern "system" fn( + *const d3d12::D3D12_ROOT_SIGNATURE_DESC, + d3d12::D3D_ROOT_SIGNATURE_VERSION, + *mut *mut ID3DBlob, + *mut *mut ID3DBlob, + ) -> crate::HRESULT; + + let desc = d3d12::D3D12_ROOT_SIGNATURE_DESC { + NumParameters: parameters.len() as _, + pParameters: parameters.as_ptr() as *const _, + NumStaticSamplers: static_samplers.len() as _, + pStaticSamplers: static_samplers.as_ptr() as _, + Flags: flags.bits(), + }; + + let mut blob = Blob::null(); + let mut error = Error::null(); + let hr = unsafe { + let func: libloading::Symbol = self.lib.get(b"D3D12SerializeRootSignature")?; + func( + &desc, + version as _, + blob.mut_void() as *mut *mut _, + error.mut_void() as *mut *mut _, + ) + }; + + Ok(((blob, error), hr)) + } +} impl RootSignature { + #[cfg(feature = "libstatic")] pub fn serialize( version: RootSignatureVersion, parameters: &[RootParameter], static_samplers: &[StaticSampler], flags: RootSignatureFlags, - ) -> D3DResult<(Blob, Error)> { + ) -> BlobResult { let mut blob = Blob::null(); let mut error = Error::null(); diff --git a/src/device.rs b/src/device.rs index fd3fa5f595..4e9307a8e2 100644 --- a/src/device.rs +++ b/src/device.rs @@ -9,17 +9,47 @@ use winapi::um::d3d12; use winapi::Interface; use {pso, query, queue}; use { - Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, FeatureLevel, + Blob, CachedPSO, CommandAllocator, CommandQueue, D3DResult, DescriptorHeap, Fence, GraphicsCommandList, NodeMask, PipelineState, QueryHeap, Resource, RootSignature, Shader, TextureAddressMode, }; pub type Device = WeakPtr; +#[cfg(feature = "libloading")] +impl crate::D3D12Lib { + pub fn create_device( + &self, + adapter: WeakPtr, + feature_level: crate::FeatureLevel, + ) -> libloading::Result> { + type Fun = extern "system" fn( + *mut winapi::um::unknwnbase::IUnknown, + winapi::um::d3dcommon::D3D_FEATURE_LEVEL, + winapi::shared::guiddef::REFGUID, + *mut *mut winapi::ctypes::c_void, + ) -> crate::HRESULT; + + let mut device = Device::null(); + let hr = unsafe { + let func: libloading::Symbol = self.lib.get(b"D3D12CreateDevice")?; + func( + adapter.as_unknown() as *const _ as *mut _, + feature_level as _, + &d3d12::ID3D12Device::uuidof(), + device.mut_void(), + ) + }; + + Ok((device, hr)) + } +} + impl Device { + #[cfg(feature = "libstatic")] pub fn create( adapter: WeakPtr, - feature_level: FeatureLevel, + feature_level: crate::FeatureLevel, ) -> D3DResult { let mut device = Device::null(); let hr = unsafe { diff --git a/src/dxgi.rs b/src/dxgi.rs index ad8b91e448..14a971e328 100644 --- a/src/dxgi.rs +++ b/src/dxgi.rs @@ -2,7 +2,7 @@ use com::WeakPtr; use std::ptr; use winapi::shared::windef::HWND; use winapi::shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgiformat, dxgitype}; -use winapi::um::d3d12; +use winapi::um::{dxgidebug, d3d12}; use winapi::Interface; use {CommandQueue, D3DResult, Resource, SampleDesc, HRESULT}; @@ -42,10 +42,67 @@ pub enum AlphaMode { pub type Adapter1 = WeakPtr; pub type Factory2 = WeakPtr; pub type Factory4 = WeakPtr; +pub type InfoQueue = WeakPtr; pub type SwapChain = WeakPtr; pub type SwapChain1 = WeakPtr; pub type SwapChain3 = WeakPtr; +#[cfg(feature = "libloading")] +pub struct DxgiLib { + lib: libloading::Library, +} + +#[cfg(feature = "libloading")] +impl DxgiLib { + pub fn new() -> libloading::Result { + libloading::Library::new("dxgi.dll") + .map(|lib| DxgiLib { + lib, + }) + } + + pub fn create_factory2( + &self, flags: FactoryCreationFlags + ) -> libloading::Result> { + type Fun = extern "system" fn( + winapi::shared::minwindef::UINT, + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut factory = Factory4::null(); + let hr = unsafe { + let func: libloading::Symbol = self.lib.get(b"CreateDXGIFactory2")?; + func( + flags.bits(), + &dxgi1_4::IDXGIFactory4::uuidof(), + factory.mut_void(), + ) + }; + + Ok((factory, hr)) + } + + pub fn get_debug_interface1(&self) -> libloading::Result> { + type Fun = extern "system" fn( + winapi::shared::minwindef::UINT, + winapi::shared::guiddef::REFIID, + *mut *mut winapi::ctypes::c_void, + ) -> HRESULT; + + let mut queue = InfoQueue::null(); + let hr = unsafe { + let func: libloading::Symbol = self.lib.get(b"DXGIGetDebugInterface1")?; + func( + 0, + &dxgidebug::IDXGIInfoQueue::uuidof(), + queue.mut_void(), + ) + }; + Ok((queue, hr)) + } +} + // TODO: strong types pub struct SwapchainDesc { pub width: u32, @@ -103,6 +160,7 @@ impl Factory2 { } impl Factory4 { + #[cfg(feature = "libstatic")] pub fn create(flags: FactoryCreationFlags) -> D3DResult { let mut factory = Factory4::null(); let hr = unsafe { diff --git a/src/lib.rs b/src/lib.rs index b681f09a5b..71c7e78f95 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -83,3 +83,8 @@ impl Error { CStr::from_ptr(data as *const _ as *const _) } } + +#[cfg(feature = "libloading")] +pub struct D3D12Lib { + lib: libloading::Library, +}