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
145
146
147
use crate::d3d;
use crate::d3d11;
use crate::d3d12;
use crate::impl_interface;
use crate::result::{hresult, HResult};
use crate::Interface;
use com_ptr::ComPtr;
use winapi::um::d3d11::*;
use winapi::um::d3d11on12::*;
use winapi::um::unknwnbase::IUnknown;

pub struct D3D11ResourceFlags {
    pub bind_flags: d3d11::BindFlags,
    pub misc_flags: Option<d3d11::ResourceMiscFlags>,
    pub cpu_access_flags: Option<d3d11::CPUAccessFlags>,
    pub structure_byte_stride: u32,
}
impl D3D11ResourceFlags {
    fn to_c_struct(&self) -> D3D11_RESOURCE_FLAGS {
        D3D11_RESOURCE_FLAGS {
            BindFlags: self.bind_flags.0,
            MiscFlags: self.misc_flags.map_or(0, |f| f.0),
            CPUAccessFlags: self.cpu_access_flags.map_or(0, |f| f.0),
            StructureByteStride: self.structure_byte_stride,
        }
    }
}

pub trait IDevice: Interface {
    fn acquire_wrapped_resources(&self, resources: &[&impl d3d11::IResource]);
    fn create_wrapped_resource(
        &self,
        resource12: &impl d3d12::IResource,
        flags11: D3D11ResourceFlags,
        in_state: d3d12::ResourceStates,
        out_state: d3d12::ResourceStates,
    ) -> Result<d3d11::Resource, HResult>;
    fn release_wrapped_resources(&self, resources: &[&impl d3d11::IResource]);
}
pub trait IDevice1: IDevice {
    fn get_d3d12_device<T: d3d12::IDevice>(&self) -> Result<T, HResult>;
}
#[derive(Clone, Debug)]
pub struct Device(ComPtr<ID3D11On12Device>);
/*
#[derive(Clone, Debug)]
pub struct Device1(ComPtr<ID3D11On12Device1>);
*/
macro_rules! impl_device {
    ($s: ident, $interface: ident, Device) => {
        impl_interface!($s, $interface);
        impl IDevice for $s {
            fn acquire_wrapped_resources(&self, resources: &[&impl d3d11::IResource]) {
                unsafe {
                    let mut c_resources = resources.iter().map(|r| r.as_ptr()).collect::<Vec<_>>();
                    self.0.AcquireWrappedResources(
                        c_resources.as_mut_ptr() as *mut *mut ID3D11Resource,
                        c_resources.len() as u32,
                    );
                }
            }
            fn create_wrapped_resource(
                &self,
                resource12: &impl d3d12::IResource,
                flags11: D3D11ResourceFlags,
                in_state: d3d12::ResourceStates,
                out_state: d3d12::ResourceStates,
            ) -> Result<d3d11::Resource, HResult> {
                Ok(d3d11::Resource::new(ComPtr::new(|| {
                    let mut p = std::ptr::null_mut();
                    let res = unsafe {
                        self.0.CreateWrappedResource(
                            resource12.as_ptr() as *mut IUnknown,
                            &flags11.to_c_struct(),
                            in_state.0,
                            out_state.0,
                            &d3d11::Resource::uuidof().into(),
                            &mut p,
                        )
                    };
                    hresult(p as *mut ID3D11Resource, res)
                })?))
            }
            fn release_wrapped_resources(&self, resources: &[&impl d3d11::IResource]) {
                unsafe {
                    let mut c_resources = resources.iter().map(|r| r.as_ptr()).collect::<Vec<_>>();
                    self.0.ReleaseWrappedResources(
                        c_resources.as_mut_ptr() as *mut *mut ID3D11Resource,
                        c_resources.len() as u32,
                    );
                }
            }
        }
    };
    ($s: ident, $interface: ident, Device1) => {
        impl_interface!($s, $interface);
        pub impl IDevice1 for $s {
            fn get_d3d12_device<T: d3d12::IDevice>(&self) -> Result<T, HResult> {
                Ok(T::new(ComPtr::new(|| {
                    let mut p = std::ptr::null_mut();
                    let res = unsafe { self.0.GetD3D12Device(&T::uuidof().into(), &mut p) };
                    hresult(p as *mut <T as Interface>::APIType, res)
                })?))
            }
        }
    };
}
impl_device!(Device, ID3D11On12Device, Device);

pub fn create_device(
    device12: &impl d3d12::IDevice,
    flags: Option<d3d11::CreateDeviceFlags>,
    feature_levels: &[d3d::FeatureLevel],
    command_queues: &[&impl d3d12::ICommandQueue],
    node_mask: u32,
) -> Result<(d3d11::Device, d3d11::DeviceContext, d3d::FeatureLevel), HResult> {
    unsafe {
        let mut device = std::ptr::null_mut();
        let mut device_context = std::ptr::null_mut();
        let mut feature_level = 0;
        let c_feature_levels = feature_levels.iter().map(|&l| l.into()).collect::<Vec<_>>();
        let mut c_command_queues = command_queues
            .iter()
            .map(|c| c.as_ptr() as *mut IUnknown)
            .collect::<Vec<_>>();
        let res = D3D11On12CreateDevice(
            device12.as_ptr() as *mut IUnknown,
            flags.map_or(0, |f| f.0),
            c_feature_levels.as_ptr(),
            c_feature_levels.len() as u32,
            c_command_queues.as_mut_ptr(),
            c_command_queues.len() as u32,
            node_mask,
            &mut device,
            &mut device_context,
            &mut feature_level,
        );
        if res < 0 {
            return Err(res.into());
        }
        Ok((
            d3d11::Device::new(ComPtr::from_raw(device)),
            d3d11::DeviceContext::new(ComPtr::from_raw(device_context)),
            feature_level.into(),
        ))
    }
}