19: Dynamic loading for D3D12 device and DXGI r=msiglreith a=kvark

Fixes #18

Users can opt into static/implicit linking, or explicit one with "libloading", or even both (to make features truly additive).
I believe these changes cover the entry points we need to get everything running on any other Windows than 10.

Co-authored-by: Dzmitry Malyshau <kvarkus@gmail.com>
This commit is contained in:
bors[bot]
2019-10-31 22:25:42 +00:00
committed by GitHub
7 changed files with 179 additions and 12 deletions

View File

@@ -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"]

View File

@@ -24,3 +24,6 @@ install:
build: false
test_script:
- cargo check
- cargo check --features libloading
- cargo check --features libstatic
- cargo check --all-features

View File

@@ -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<d3d12sdklayers::ID3D12Debug>;
impl Debug {
pub fn get_interface() -> D3DResult<Self> {
#[cfg(feature = "libloading")]
impl crate::D3D12Lib {
pub fn get_debug_interface(&self) -> libloading::Result<crate::D3DResult<Debug>> {
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<Fun> = 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<Self> {
let mut debug = Debug::null();
let hr = unsafe {
winapi::um::d3d12::D3D12GetDebugInterface(
&d3d12sdklayers::ID3D12Debug::uuidof(),
debug.mut_void(),
)
};
(debug, hr)

View File

@@ -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<d3d12::ID3D12RootSignature>;
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<BlobResult> {
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<Fun> = 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();

View File

@@ -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<d3d12::ID3D12Device>;
#[cfg(feature = "libloading")]
impl crate::D3D12Lib {
pub fn create_device<I: Interface>(
&self,
adapter: WeakPtr<I>,
feature_level: crate::FeatureLevel,
) -> libloading::Result<D3DResult<Device>> {
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<Fun> = 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<I: Interface>(
adapter: WeakPtr<I>,
feature_level: FeatureLevel,
feature_level: crate::FeatureLevel,
) -> D3DResult<Self> {
let mut device = Device::null();
let hr = unsafe {

View File

@@ -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<dxgi::IDXGIAdapter1>;
pub type Factory2 = WeakPtr<dxgi1_2::IDXGIFactory2>;
pub type Factory4 = WeakPtr<dxgi1_4::IDXGIFactory4>;
pub type InfoQueue = WeakPtr<dxgidebug::IDXGIInfoQueue>;
pub type SwapChain = WeakPtr<dxgi::IDXGISwapChain>;
pub type SwapChain1 = WeakPtr<dxgi1_2::IDXGISwapChain1>;
pub type SwapChain3 = WeakPtr<dxgi1_4::IDXGISwapChain3>;
#[cfg(feature = "libloading")]
pub struct DxgiLib {
lib: libloading::Library,
}
#[cfg(feature = "libloading")]
impl DxgiLib {
pub fn new() -> libloading::Result<Self> {
libloading::Library::new("dxgi.dll")
.map(|lib| DxgiLib {
lib,
})
}
pub fn create_factory2(
&self, flags: FactoryCreationFlags
) -> libloading::Result<D3DResult<Factory4>> {
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<Fun> = 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<D3DResult<InfoQueue>> {
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<Fun> = 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<Self> {
let mut factory = Factory4::null();
let hr = unsafe {

View File

@@ -83,3 +83,8 @@ impl Error {
CStr::from_ptr(data as *const _ as *const _)
}
}
#[cfg(feature = "libloading")]
pub struct D3D12Lib {
lib: libloading::Library,
}