use std::sync::Arc;
use parking_lot::Mutex;
use windows::Win32::Foundation::HANDLE;
use windows::Win32::Graphics::Direct3D12::ID3D12Resource;
use windows::core::Interface;
use crate::error::{Error, Result};
use super::ExportedFrame;
impl ExportedFrame {
pub fn into_wgpu_texture(mut self, device: &wgpu::Device) -> Result<wgpu::Texture> {
let (width, height) = (self.width(), self.height());
let handle = HANDLE(self.shared_handle());
let resource = {
let hal_device = unsafe { device.as_hal::<wgpu_hal::api::Dx12>() };
let Some(hal_device) = hal_device else {
return Err(Error::WgpuImport(
"wgpu device is not on the DX12 backend".into(),
));
};
let mut resource: Option<ID3D12Resource> = None;
unsafe {
hal_device
.raw_device()
.OpenSharedHandle(handle, &mut resource)
}
.map_err(|e| {
Error::WgpuImport(format!("ID3D12Device::OpenSharedHandle failed: {e}"))
})?;
resource
.ok_or_else(|| Error::WgpuImport("OpenSharedHandle returned no resource".into()))?
};
let buffer = self
.buffer
.take()
.expect("buffer present until drop/presented");
let payload = Arc::new(Mutex::new(Some((Arc::clone(&self.shared), buffer))));
let on_release = {
let payload = Arc::clone(&payload);
Box::new(move || {
if let Some((shared, buffer)) = payload.lock().take() {
super::return_buffer(&shared, buffer);
}
})
};
let attached = super::platform::on_resource_release(resource.as_raw(), on_release);
if !attached {
tracing::warn!(
"export: could not attach the D3D12 release callback; retiring the buffer"
);
if let Some((shared, buffer)) = payload.lock().take() {
super::retire_buffer(&shared, buffer);
}
}
let hal_texture = unsafe {
wgpu_hal::dx12::Device::texture_from_raw(
resource,
wgpu::TextureFormat::Bgra8Unorm,
wgpu::TextureDimension::D2,
wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
1,
1,
)
};
let desc = super::exported_texture_desc(width, height);
Ok(unsafe {
device.create_texture_from_hal::<wgpu_hal::api::Dx12>(
hal_texture,
&desc,
wgpu::TextureUses::empty(),
)
})
}
}