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
use device::Device;
use device_context::DeviceContext;
use error::Error;
use flags::{CreateDeviceFlags, DriverType, FeatureLevel};
use std::ptr;
use dxgi::adapter::Adapter;
use winapi::shared::dxgi::IDXGIAdapter;
use winapi::shared::minwindef::HMODULE;
use winapi::um::d3d11::{D3D11CreateDevice, D3D11_SDK_VERSION};
pub struct DeviceBuilder<'a> {
adapter: Option<&'a Adapter>,
driver_type: Option<DriverType>,
flags: CreateDeviceFlags,
feature_levels: &'a [FeatureLevel],
software_module: HMODULE,
}
impl<'a> Default for DeviceBuilder<'a> {
fn default() -> Self {
DeviceBuilder {
adapter: None,
driver_type: None,
flags: CreateDeviceFlags::NONE,
feature_levels: &[],
software_module: ptr::null_mut(),
}
}
}
impl<'a> DeviceBuilder<'a> {
pub fn with_driver_type(mut self, driver_type: DriverType) -> Self {
assert!(
(driver_type == DriverType::Unknown || self.adapter.is_none())
&& (driver_type == DriverType::Software || self.software_module.is_null()),
"If an adapter is specified, driver_type must be `Unknown`"
);
self.driver_type = Some(driver_type);
self
}
pub fn with_adapter(mut self, adapter: &'a Adapter) -> Self {
assert!(
self.driver_type.is_none() || self.driver_type == Some(DriverType::Unknown),
"Cannot specify Adapter if driver_type is not `Unknown`"
);
self.driver_type = Some(DriverType::Unknown);
self.adapter = Some(adapter);
self
}
pub fn with_flags(mut self, flags: CreateDeviceFlags) -> Self {
assert!(
!flags.is_set(CreateDeviceFlags::SINGLETHREADED),
"SINGLETHREADED is not supported right now. If this usecase is important, please open an issue."
);
assert!(flags.validate(), "Invalid flags passed");
self.flags = flags;
self
}
pub fn with_feature_levels(mut self, levels: &'a [FeatureLevel]) -> Self {
self.feature_levels = levels;
self
}
pub unsafe fn with_software_module(mut self, software: HMODULE) -> Self {
assert!(
self.driver_type.is_none() || self.driver_type == Some(DriverType::Software),
"Cannot specify software_module if driver_type is not `Software`"
);
self.driver_type = Some(DriverType::Software);
self.software_module = software;
self
}
pub fn build(self) -> Result<(FeatureLevel, Device, DeviceContext), Error> {
unsafe {
let mut dev_ptr = ptr::null_mut();
let mut feature_level = 0;
let mut devctx_ptr = ptr::null_mut();
let hr = D3D11CreateDevice(
self.adapter
.map(|a| a.get_raw() as *mut IDXGIAdapter)
.unwrap_or(ptr::null_mut()),
self.driver_type.unwrap_or(DriverType::Hardware) as u32,
self.software_module,
self.flags.0,
if !self.feature_levels.is_empty() {
&self.feature_levels[0].0
} else {
ptr::null()
},
self.feature_levels.len() as u32,
D3D11_SDK_VERSION,
&mut dev_ptr,
&mut feature_level,
&mut devctx_ptr,
);
let dev = Error::wrap_if(hr, dev_ptr)?;
let ctx = Error::wrap_if(hr, devctx_ptr)?;
let features = FeatureLevel(feature_level);
Ok((features, dev, ctx))
}
}
}