diff --git a/CHANGELOG.md b/CHANGELOG.md index fe105fa101c..6e37be93ff9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ # Change Log -### backend-dx12-0.4.1 (01-11-2019) - - switch to explicit linking of "d3d12.dll" and "dxgi.dll" +### backend-dx12-0.4.1, backend-dx11-0.4.2 (01-11-2019) + - switch to explicit linking of "d3d12.dll", "d3d11.dll" and "dxgi.dll" ## hal-0.4.0 (23-10-2019) - all strongly typed HAL wrappers are removed diff --git a/src/backend/dx11/Cargo.toml b/src/backend/dx11/Cargo.toml index 2555d8a0514..1ec7be6b451 100644 --- a/src/backend/dx11/Cargo.toml +++ b/src/backend/dx11/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "gfx-backend-dx11" -version = "0.4.0" +version = "0.4.2" description = "DirectX-11 API backend for gfx-rs" homepage = "https://github.com/gfx-rs/gfx" repository = "https://github.com/gfx-rs/gfx" @@ -22,6 +22,7 @@ gfx-hal = { path = "../../hal", version = "0.4" } auxil = { path = "../../auxil/auxil", version = "0.1", package = "gfx-auxil" } range-alloc = { path = "../../auxil/range-alloc", version = "0.1" } bitflags = "1" +libloading = "0.5" log = { version = "0.4" } smallvec = "0.6" spirv_cross = { version = "0.16", features = ["hlsl"] } diff --git a/src/backend/dx11/src/dxgi.rs b/src/backend/dx11/src/dxgi.rs index d9835498334..50c1c56464d 100644 --- a/src/backend/dx11/src/dxgi.rs +++ b/src/backend/dx11/src/dxgi.rs @@ -1,6 +1,6 @@ use hal::adapter::{AdapterInfo, DeviceType}; -use winapi::shared::guiddef::GUID; +use winapi::shared::guiddef::{GUID, REFIID}; use winapi::shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgi1_5, winerror}; use winapi::um::unknwnbase::IUnknown; use winapi::Interface; @@ -67,10 +67,14 @@ pub(crate) enum DxgiVersion { Dxgi1_5, } -fn create_dxgi_factory1(guid: &GUID) -> Result, winerror::HRESULT> { +type DxgiFun = extern "system" fn(REFIID, *mut *mut winapi::ctypes::c_void) -> winerror::HRESULT; + +fn create_dxgi_factory1( + func: &DxgiFun, guid: &GUID +) -> Result, winerror::HRESULT> { let mut factory: *mut IUnknown = ptr::null_mut(); - let hr = unsafe { dxgi::CreateDXGIFactory1(guid, &mut factory as *mut *mut _ as *mut *mut _) }; + let hr = func(guid, &mut factory as *mut *mut _ as *mut *mut _); if winerror::SUCCEEDED(hr) { Ok(unsafe { ComPtr::from_raw(factory as *mut _) }) @@ -81,29 +85,35 @@ fn create_dxgi_factory1(guid: &GUID) -> Result, winer pub(crate) fn get_dxgi_factory( ) -> Result<(ComPtr, DxgiVersion), winerror::HRESULT> { + let library = libloading::Library::new("dxgi.dll") + .map_err(|_| -1)?; + let func: libloading::Symbol = unsafe { + library.get(b"CreateDXGIFactory1") + }.map_err(|_| -1)?; + // TODO: do we even need `create_dxgi_factory2`? - if let Ok(factory) = create_dxgi_factory1(&dxgi1_5::IDXGIFactory5::uuidof()) { + if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_5::IDXGIFactory5::uuidof()) { return Ok((factory, DxgiVersion::Dxgi1_5)); } - if let Ok(factory) = create_dxgi_factory1(&dxgi1_4::IDXGIFactory4::uuidof()) { + if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_4::IDXGIFactory4::uuidof()) { return Ok((factory, DxgiVersion::Dxgi1_4)); } - if let Ok(factory) = create_dxgi_factory1(&dxgi1_3::IDXGIFactory3::uuidof()) { + if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_3::IDXGIFactory3::uuidof()) { return Ok((factory, DxgiVersion::Dxgi1_3)); } - if let Ok(factory) = create_dxgi_factory1(&dxgi1_2::IDXGIFactory2::uuidof()) { + if let Ok(factory) = create_dxgi_factory1(&func, &dxgi1_2::IDXGIFactory2::uuidof()) { return Ok((factory, DxgiVersion::Dxgi1_2)); } - if let Ok(factory) = create_dxgi_factory1(&dxgi::IDXGIFactory1::uuidof()) { + if let Ok(factory) = create_dxgi_factory1(&func, &dxgi::IDXGIFactory1::uuidof()) { return Ok((factory, DxgiVersion::Dxgi1_0)); } // TODO: any reason why above would fail and this wouldnt? - match create_dxgi_factory1(&dxgi::IDXGIFactory::uuidof()) { + match create_dxgi_factory1(&func, &dxgi::IDXGIFactory::uuidof()) { Ok(factory) => Ok((factory, DxgiVersion::Dxgi1_0)), Err(hr) => Err(hr), } diff --git a/src/backend/dx11/src/lib.rs b/src/backend/dx11/src/lib.rs index b5c65840b37..45b75ae8dcf 100644 --- a/src/backend/dx11/src/lib.rs +++ b/src/backend/dx11/src/lib.rs @@ -5,6 +5,7 @@ extern crate auxil; extern crate range_alloc; #[macro_use] extern crate bitflags; +extern crate libloading; #[macro_use] extern crate log; extern crate parking_lot; @@ -39,7 +40,7 @@ use hal::{ use range_alloc::RangeAllocator; use winapi::shared::dxgi::{IDXGIAdapter, IDXGIFactory, IDXGISwapChain}; -use winapi::shared::minwindef::{FALSE, UINT}; +use winapi::shared::minwindef::{FALSE, UINT, HMODULE}; use winapi::shared::windef::{HWND, RECT}; use winapi::shared::{dxgiformat, winerror}; use winapi::um::winuser::GetClientRect; @@ -96,6 +97,19 @@ mod dxgi; mod internal; mod shader; +type CreateFun = extern "system" fn( + *mut IDXGIAdapter, + UINT, + HMODULE, + UINT, + *const UINT, + UINT, + UINT, + *mut *mut d3d11::ID3D11Device, + *mut UINT, + *mut *mut d3d11::ID3D11DeviceContext, +) -> winerror::HRESULT; + #[derive(Clone)] pub(crate) struct ViewInfo { resource: *mut d3d11::ID3D11Resource, @@ -116,6 +130,7 @@ impl fmt::Debug for ViewInfo { pub struct Instance { pub(crate) factory: ComPtr, pub(crate) dxgi_version: dxgi::DxgiVersion, + library: Arc, } unsafe impl Send for Instance {} @@ -256,9 +271,14 @@ impl hal::Instance for Instance { match dxgi::get_dxgi_factory() { Ok((factory, dxgi_version)) => { info!("DXGI version: {:?}", dxgi_version); + let library = Arc::new( + libloading::Library::new("d3d11.dll") + .map_err(|_| hal::UnsupportedBackend)? + ); Ok(Instance { factory, dxgi_version, + library, }) } Err(hr) => { @@ -272,6 +292,16 @@ impl hal::Instance for Instance { let mut adapters = Vec::new(); let mut idx = 0; + let func: libloading::Symbol = match unsafe { + self.library.get(b"D3D11CreateDevice") + } { + Ok(func) => func, + Err(e) => { + error!("Unable to get device creation function: {:?}", e); + return Vec::new(); + } + }; + while let Ok((adapter, info)) = dxgi::get_adapter(idx, self.factory.as_raw(), self.dxgi_version) { @@ -281,23 +311,21 @@ impl hal::Instance for Instance { // TODO: move into function? let (device, feature_level) = { - let feature_level = get_feature_level(adapter.as_raw()); + let feature_level = get_feature_level(&func, adapter.as_raw()); let mut device = ptr::null_mut(); - let hr = unsafe { - d3d11::D3D11CreateDevice( - adapter.as_raw() as *mut _, - d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, - ptr::null_mut(), - 0, - [feature_level].as_ptr(), - 1, - d3d11::D3D11_SDK_VERSION, - &mut device as *mut *mut _ as *mut *mut _, - ptr::null_mut(), - ptr::null_mut(), - ) - }; + let hr = func( + adapter.as_raw() as *mut _, + d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, + ptr::null_mut(), + 0, + [feature_level].as_ptr(), + 1, + d3d11::D3D11_SDK_VERSION, + &mut device as *mut *mut _ as *mut *mut _, + ptr::null_mut(), + ptr::null_mut(), + ); if !winerror::SUCCEEDED(hr) { continue; @@ -384,6 +412,7 @@ impl hal::Instance for Instance { let physical_device = PhysicalDevice { adapter, + library: Arc::clone(&self.library), features, limits, memory_properties, @@ -421,6 +450,7 @@ impl hal::Instance for Instance { pub struct PhysicalDevice { adapter: ComPtr, + library: Arc, features: hal::Features, limits: hal::Limits, memory_properties: adapter::MemoryProperties, @@ -437,7 +467,7 @@ unsafe impl Send for PhysicalDevice {} unsafe impl Sync for PhysicalDevice {} // TODO: does the adapter we get earlier matter for feature level? -fn get_feature_level(adapter: *mut IDXGIAdapter) -> d3dcommon::D3D_FEATURE_LEVEL { +fn get_feature_level(func: &CreateFun, adapter: *mut IDXGIAdapter) -> d3dcommon::D3D_FEATURE_LEVEL { let requested_feature_levels = [ d3dcommon::D3D_FEATURE_LEVEL_11_1, d3dcommon::D3D_FEATURE_LEVEL_11_0, @@ -449,40 +479,36 @@ fn get_feature_level(adapter: *mut IDXGIAdapter) -> d3dcommon::D3D_FEATURE_LEVEL ]; let mut feature_level = d3dcommon::D3D_FEATURE_LEVEL_9_1; - let hr = unsafe { - d3d11::D3D11CreateDevice( - adapter, - d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, - ptr::null_mut(), - 0, - requested_feature_levels[..].as_ptr(), - requested_feature_levels.len() as _, - d3d11::D3D11_SDK_VERSION, - ptr::null_mut(), - &mut feature_level as *mut _, - ptr::null_mut(), - ) - }; + let hr = func( + adapter, + d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, + ptr::null_mut(), + 0, + requested_feature_levels[..].as_ptr(), + requested_feature_levels.len() as _, + d3d11::D3D11_SDK_VERSION, + ptr::null_mut(), + &mut feature_level as *mut _, + ptr::null_mut(), + ); if !winerror::SUCCEEDED(hr) { // if there is no 11.1 runtime installed, requesting // `D3D_FEATURE_LEVEL_11_1` will return E_INVALIDARG so we just retry // without that if hr == winerror::E_INVALIDARG { - let hr = unsafe { - d3d11::D3D11CreateDevice( - adapter, - d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, - ptr::null_mut(), - 0, - requested_feature_levels[1 ..].as_ptr(), - (requested_feature_levels.len() - 1) as _, - d3d11::D3D11_SDK_VERSION, - ptr::null_mut(), - &mut feature_level as *mut _, - ptr::null_mut(), - ) - }; + let hr = func( + adapter, + d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, + ptr::null_mut(), + 0, + requested_feature_levels[1 ..].as_ptr(), + (requested_feature_levels.len() - 1) as _, + d3d11::D3D11_SDK_VERSION, + ptr::null_mut(), + &mut feature_level as *mut _, + ptr::null_mut(), + ); if !winerror::SUCCEEDED(hr) { // TODO: device might not support any feature levels? @@ -501,12 +527,16 @@ impl adapter::PhysicalDevice for PhysicalDevice { families: &[(&QueueFamily, &[queue::QueuePriority])], requested_features: hal::Features, ) -> Result, hal::device::CreationError> { + let func: libloading::Symbol = self.library + .get(b"D3D11CreateDevice") + .unwrap(); + let (device, cxt) = { if !self.features().contains(requested_features) { return Err(hal::device::CreationError::MissingFeature); } - let feature_level = get_feature_level(self.adapter.as_raw()); + let feature_level = get_feature_level(&func, self.adapter.as_raw()); let mut returned_level = d3dcommon::D3D_FEATURE_LEVEL_9_1; #[cfg(debug_assertions)] @@ -517,7 +547,7 @@ impl adapter::PhysicalDevice for PhysicalDevice { // TODO: request debug device only on debug config? let mut device = ptr::null_mut(); let mut cxt = ptr::null_mut(); - let hr = d3d11::D3D11CreateDevice( + let hr = func( self.adapter.as_raw() as *mut _, d3dcommon::D3D_DRIVER_TYPE_UNKNOWN, ptr::null_mut(), @@ -547,7 +577,7 @@ impl adapter::PhysicalDevice for PhysicalDevice { // TODO: deferred context => 1 cxt/queue? let queue_groups = families .into_iter() - .map(|&(family, prio)| { + .map(|&(_family, prio)| { assert_eq!(prio.len(), 1); let mut group = queue::QueueGroup::new(queue::QueueFamilyId(0)); @@ -711,7 +741,7 @@ impl window::Surface for Surface { true } - fn capabilities(&self, physical_device: &PhysicalDevice) -> window::SurfaceCapabilities { + fn capabilities(&self, _physical_device: &PhysicalDevice) -> window::SurfaceCapabilities { let current_extent = unsafe { let mut rect: RECT = mem::zeroed(); assert_ne!(