1use windows::Graphics::DirectX::Direct3D11::IDirect3DDevice;
2use windows::Win32::Foundation::HMODULE;
3use windows::Win32::Graphics::Direct3D::{
4 D3D_DRIVER_TYPE_HARDWARE, D3D_FEATURE_LEVEL, D3D_FEATURE_LEVEL_9_1, D3D_FEATURE_LEVEL_9_2,
5 D3D_FEATURE_LEVEL_9_3, D3D_FEATURE_LEVEL_10_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0,
6 D3D_FEATURE_LEVEL_11_1,
7};
8use windows::Win32::Graphics::Direct3D11::{
9 D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_SDK_VERSION, D3D11CreateDevice, ID3D11Device,
10 ID3D11DeviceContext,
11};
12use windows::Win32::Graphics::Dxgi::IDXGIDevice;
13use windows::Win32::System::WinRT::Direct3D11::CreateDirect3D11DeviceFromDXGIDevice;
14use windows::core::Interface;
15
16#[derive(thiserror::Error, Eq, PartialEq, Clone, Debug)]
17pub enum Error {
18 #[error("Failed to create DirectX device with the recommended feature levels")]
19 FeatureLevelNotSatisfied,
20 #[error("Windows API Error: {0}")]
21 WindowsError(#[from] windows::core::Error),
22}
23
24pub struct SendDirectX<T>(pub T);
26
27impl<T> SendDirectX<T> {
28 #[must_use]
38 #[inline]
39 pub const fn new(device: T) -> Self {
40 Self(device)
41 }
42}
43
44#[allow(clippy::non_send_fields_in_send_ty)]
45unsafe impl<T> Send for SendDirectX<T> {}
46
47#[inline]
49pub fn create_d3d_device() -> Result<(ID3D11Device, ID3D11DeviceContext), Error> {
50 let feature_flags = [
55 D3D_FEATURE_LEVEL_11_1,
56 D3D_FEATURE_LEVEL_11_0,
57 D3D_FEATURE_LEVEL_10_1,
58 D3D_FEATURE_LEVEL_10_0,
59 D3D_FEATURE_LEVEL_9_3,
60 D3D_FEATURE_LEVEL_9_2,
61 D3D_FEATURE_LEVEL_9_1,
62 ];
63
64 let mut d3d_device = None;
65 let mut feature_level = D3D_FEATURE_LEVEL::default();
66 let mut d3d_device_context = None;
67 unsafe {
68 D3D11CreateDevice(
69 None,
70 D3D_DRIVER_TYPE_HARDWARE,
71 HMODULE::default(),
72 D3D11_CREATE_DEVICE_BGRA_SUPPORT,
73 Some(&feature_flags),
74 D3D11_SDK_VERSION,
75 Some(&mut d3d_device),
76 Some(&mut feature_level),
77 Some(&mut d3d_device_context),
78 )?;
79 };
80
81 if feature_level.0 < D3D_FEATURE_LEVEL_11_0.0 {
82 return Err(Error::FeatureLevelNotSatisfied);
83 }
84
85 Ok((d3d_device.unwrap(), d3d_device_context.unwrap()))
86}
87
88#[inline]
90pub fn create_direct3d_device(d3d_device: &ID3D11Device) -> Result<IDirect3DDevice, Error> {
91 let dxgi_device: IDXGIDevice = d3d_device.cast()?;
92 let inspectable = unsafe { CreateDirect3D11DeviceFromDXGIDevice(&dxgi_device)? };
93 let device: IDirect3DDevice = inspectable.cast()?;
94
95 Ok(device)
96}