1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
|
use std::ptr;
use winapi::{
shared::{
dxgi,
minwindef::{HMODULE, UINT},
winerror,
},
um::{d3d11, d3d11_1, d3d11_2, d3dcommon},
};
use crate::auxil::dxgi::result::HResult;
type D3D11CreateDeviceFun = unsafe extern "system" fn(
*mut dxgi::IDXGIAdapter,
d3dcommon::D3D_DRIVER_TYPE,
HMODULE,
UINT,
*const d3dcommon::D3D_FEATURE_LEVEL,
UINT,
UINT,
*mut *mut d3d11::ID3D11Device,
*mut d3dcommon::D3D_FEATURE_LEVEL,
*mut *mut d3d11::ID3D11DeviceContext,
) -> d3d12::HRESULT;
pub(super) struct D3D11Lib {
// We use the os specific symbol to drop the lifetime parameter.
//
// SAFETY: we must ensure this outlives the Library.
d3d11_create_device: libloading::os::windows::Symbol<D3D11CreateDeviceFun>,
lib: libloading::Library,
}
impl D3D11Lib {
pub fn new() -> Option<Self> {
unsafe {
let lib = libloading::Library::new("d3d11.dll").ok()?;
let d3d11_create_device = lib
.get::<D3D11CreateDeviceFun>(b"D3D11CreateDevice")
.ok()?
.into_raw();
Some(Self {
lib,
d3d11_create_device,
})
}
}
pub fn create_device(
&self,
adapter: d3d12::DxgiAdapter,
) -> Option<(super::D3D11Device, d3dcommon::D3D_FEATURE_LEVEL)> {
let feature_levels = [
d3dcommon::D3D_FEATURE_LEVEL_11_1,
d3dcommon::D3D_FEATURE_LEVEL_11_0,
d3dcommon::D3D_FEATURE_LEVEL_10_1,
d3dcommon::D3D_FEATURE_LEVEL_10_0,
d3dcommon::D3D_FEATURE_LEVEL_9_3,
d3dcommon::D3D_FEATURE_LEVEL_9_2,
d3dcommon::D3D_FEATURE_LEVEL_9_1,
];
let mut device = d3d12::WeakPtr::<d3d11::ID3D11Device>::null();
let mut feature_level: d3dcommon::D3D_FEATURE_LEVEL = 0;
// We need to try this twice. If the first time fails due to E_INVALIDARG
// we are running on a machine without a D3D11.1 runtime, and need to
// retry without the feature level 11_1 feature level.
//
// Why they thought this was a good API, who knows.
let mut hr = unsafe {
(self.d3d11_create_device)(
adapter.as_mut_ptr() as *mut _,
d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
ptr::null_mut(), // software implementation DLL???
0, // flags
feature_levels.as_ptr(),
feature_levels.len() as u32,
d3d11::D3D11_SDK_VERSION,
device.mut_self(),
&mut feature_level,
ptr::null_mut(), // device context
)
};
// Try again without FL11_1
if hr == winerror::E_INVALIDARG {
hr = unsafe {
(self.d3d11_create_device)(
adapter.as_mut_ptr() as *mut _,
d3dcommon::D3D_DRIVER_TYPE_UNKNOWN,
ptr::null_mut(), // software implementation DLL???
0, // flags
feature_levels[1..].as_ptr(),
feature_levels[1..].len() as u32,
d3d11::D3D11_SDK_VERSION,
device.mut_self(),
&mut feature_level,
ptr::null_mut(), // device context
)
};
}
// Any errors here are real and we should complain about
if let Err(err) = hr.into_result() {
log::error!("Failed to make a D3D11 device: {}", err);
return None;
}
// We always try to upcast in highest -> lowest order
// Device -> Device2
unsafe {
match device.cast::<d3d11_2::ID3D11Device2>().into_result() {
Ok(device2) => {
device.destroy();
return Some((super::D3D11Device::Device2(device2), feature_level));
}
Err(hr) => {
log::info!("Failed to cast device to ID3D11Device2: {}", hr)
}
}
}
// Device -> Device1
unsafe {
match device.cast::<d3d11_1::ID3D11Device1>().into_result() {
Ok(device1) => {
device.destroy();
return Some((super::D3D11Device::Device1(device1), feature_level));
}
Err(hr) => {
log::info!("Failed to cast device to ID3D11Device1: {}", hr)
}
}
}
Some((super::D3D11Device::Device(device), feature_level))
}
}
|