Skip to main content

asdf_overlay/
interop.rs

1use core::ptr;
2
3use anyhow::Context;
4use asdf_overlay_event::GpuLuid;
5use parking_lot::Mutex;
6use windows::{
7    Win32::{
8        Foundation::HMODULE,
9        Graphics::{
10            Direct3D::{D3D_DRIVER_TYPE_HARDWARE, D3D_DRIVER_TYPE_UNKNOWN},
11            Direct3D11::{
12                D3D11_CREATE_DEVICE_BGRA_SUPPORT, D3D11_SDK_VERSION, D3D11CreateDevice,
13                ID3D11Device, ID3D11DeviceContext,
14            },
15            Dxgi::{IDXGIAdapter, IDXGIDevice},
16        },
17    },
18    core::Interface,
19};
20
21/// Direct3D 11 device for storing and sharing overlay texture with other graphics backend.
22#[non_exhaustive]
23pub struct DxInterop {
24    /// This is the GPU adapter used by the surface.
25    /// Overlay surface texture must be created with this GPU.
26    /// Otherwise, surface cannot be rendered.
27    pub gpu_id: GpuLuid,
28
29    /// Interop Direct3D 11 device.
30    pub device: ID3D11Device,
31
32    /// Interop Direct3D 11 device context.
33    pub cx: Mutex<ID3D11DeviceContext>,
34}
35
36impl DxInterop {
37    /// Create new [`DxInterop`].
38    /// * If `adapter` is provided, it will use provided GPU adapter.
39    /// * If `adapter` it not provided, it will use system provided GPU adapter.
40    pub fn new(adapter: Option<&IDXGIAdapter>) -> anyhow::Result<Self> {
41        unsafe {
42            let mut device = None;
43            let mut cx = None;
44            D3D11CreateDevice(
45                adapter,
46                if adapter.is_some() {
47                    D3D_DRIVER_TYPE_UNKNOWN
48                } else {
49                    D3D_DRIVER_TYPE_HARDWARE
50                },
51                HMODULE(ptr::null_mut()),
52                D3D11_CREATE_DEVICE_BGRA_SUPPORT,
53                None,
54                D3D11_SDK_VERSION,
55                Some(&mut device),
56                None,
57                Some(&mut cx),
58            )
59            .context("failed to create D3D11 interop device")?;
60            let device = device.unwrap();
61            let cx = cx.unwrap();
62
63            let luid = device
64                .cast::<IDXGIDevice>()?
65                .GetAdapter()?
66                .GetDesc()?
67                .AdapterLuid;
68            Ok(Self {
69                gpu_id: GpuLuid {
70                    low: luid.LowPart,
71                    high: luid.HighPart,
72                },
73                device,
74                cx: Mutex::new(cx),
75            })
76        }
77    }
78}