Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[dx11] explicit library loading #3077

Merged
merged 2 commits into from
Nov 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# Change Log

### 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
- all use of `failure` is removed
Expand Down
3 changes: 2 additions & 1 deletion src/backend/dx11/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "gfx-backend-dx11"
version = "0.4.0"
version = "0.4.1"
description = "DirectX-11 API backend for gfx-rs"
homepage = "https://github.com/gfx-rs/gfx"
repository = "https://github.com/gfx-rs/gfx"
Expand All @@ -23,6 +23,7 @@ auxil = { path = "../../auxil/auxil", version = "0.2", package = "gfx-auxil", fe
hal = { path = "../../hal", version = "0.4", package = "gfx-hal" }
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"] }
Expand Down
28 changes: 19 additions & 9 deletions src/backend/dx11/src/dxgi.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use hal::adapter::{AdapterInfo, DeviceType};

use winapi::{
shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgi1_5, guiddef::GUID, winerror},
shared::{dxgi, dxgi1_2, dxgi1_3, dxgi1_4, dxgi1_5, guiddef::{GUID, REFIID}, winerror},
um::unknwnbase::IUnknown,
Interface,
};
Expand Down Expand Up @@ -65,10 +65,14 @@ pub(crate) enum DxgiVersion {
Dxgi1_5,
}

fn create_dxgi_factory1(guid: &GUID) -> Result<ComPtr<dxgi::IDXGIFactory>, 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<ComPtr<dxgi::IDXGIFactory>, 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 _) })
Expand All @@ -79,29 +83,35 @@ fn create_dxgi_factory1(guid: &GUID) -> Result<ComPtr<dxgi::IDXGIFactory>, winer

pub(crate) fn get_dxgi_factory(
) -> Result<(ComPtr<dxgi::IDXGIFactory>, DxgiVersion), winerror::HRESULT> {
let library = libloading::Library::new("dxgi.dll")
.map_err(|_| -1)?;
let func: libloading::Symbol<DxgiFun> = 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),
}
Expand Down
127 changes: 78 additions & 49 deletions src/backend/dx11/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use winapi::{
shared::{
dxgi::{IDXGIAdapter, IDXGIFactory, IDXGISwapChain},
dxgiformat,
minwindef::{FALSE, UINT},
minwindef::{FALSE, UINT, HMODULE},
windef::{HWND, RECT},
winerror,
},
Expand Down Expand Up @@ -85,6 +85,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,
Expand All @@ -105,6 +118,7 @@ impl fmt::Debug for ViewInfo {
pub struct Instance {
pub(crate) factory: ComPtr<IDXGIFactory>,
pub(crate) dxgi_version: dxgi::DxgiVersion,
library: Arc<libloading::Library>,
}

unsafe impl Send for Instance {}
Expand Down Expand Up @@ -245,9 +259,14 @@ impl hal::Instance<Backend> 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) => {
Expand All @@ -261,6 +280,16 @@ impl hal::Instance<Backend> for Instance {
let mut adapters = Vec::new();
let mut idx = 0;

let func: libloading::Symbol<CreateFun> = 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)
{
Expand All @@ -270,23 +299,21 @@ impl hal::Instance<Backend> 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;
Expand Down Expand Up @@ -373,6 +400,7 @@ impl hal::Instance<Backend> for Instance {

let physical_device = PhysicalDevice {
adapter,
library: Arc::clone(&self.library),
features,
limits,
memory_properties,
Expand Down Expand Up @@ -410,6 +438,7 @@ impl hal::Instance<Backend> for Instance {

pub struct PhysicalDevice {
adapter: ComPtr<IDXGIAdapter>,
library: Arc<libloading::Library>,
features: hal::Features,
limits: hal::Limits,
memory_properties: adapter::MemoryProperties,
Expand All @@ -426,7 +455,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,
Expand All @@ -438,40 +467,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?
Expand All @@ -490,12 +515,16 @@ impl adapter::PhysicalDevice<Backend> for PhysicalDevice {
families: &[(&QueueFamily, &[queue::QueuePriority])],
requested_features: hal::Features,
) -> Result<adapter::Gpu<Backend>, hal::device::CreationError> {
let func: libloading::Symbol<CreateFun> = 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)]
Expand All @@ -506,7 +535,7 @@ impl adapter::PhysicalDevice<Backend> 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(),
Expand Down Expand Up @@ -536,7 +565,7 @@ impl adapter::PhysicalDevice<Backend> 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));

Expand Down Expand Up @@ -700,7 +729,7 @@ impl window::Surface<Backend> 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!(
Expand Down