use windows::Win32::Foundation::{CloseHandle, E_POINTER, HANDLE};
use windows::Win32::Graphics::Direct3D12::{
D3D12_CPU_PAGE_PROPERTY_UNKNOWN, D3D12_FENCE_FLAG_SHARED, D3D12_HEAP_FLAG_SHARED,
D3D12_HEAP_PROPERTIES, D3D12_HEAP_TYPE_DEFAULT, D3D12_MEMORY_POOL_UNKNOWN, D3D12_RESOURCE_DESC,
D3D12_RESOURCE_DIMENSION_TEXTURE2D, D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
D3D12_RESOURCE_STATE_COMMON, D3D12_TEXTURE_LAYOUT_UNKNOWN, ID3D12CommandQueue, ID3D12Device,
ID3D12Fence, ID3D12Resource,
};
use windows::Win32::Graphics::Dxgi::Common::{DXGI_FORMAT, DXGI_SAMPLE_DESC};
use windows::core::{Error, PCWSTR};
const GENERIC_ALL: u32 = 0x1000_0000;
pub struct SharedSurface {
resource: ID3D12Resource,
handle: HANDLE,
width: u32,
height: u32,
format: DXGI_FORMAT,
}
impl SharedSurface {
pub fn new(
device: &ID3D12Device,
width: u32,
height: u32,
format: DXGI_FORMAT,
) -> windows::core::Result<Self> {
let heap = D3D12_HEAP_PROPERTIES {
Type: D3D12_HEAP_TYPE_DEFAULT,
CPUPageProperty: D3D12_CPU_PAGE_PROPERTY_UNKNOWN,
MemoryPoolPreference: D3D12_MEMORY_POOL_UNKNOWN,
CreationNodeMask: 1,
VisibleNodeMask: 1,
};
let desc = D3D12_RESOURCE_DESC {
Dimension: D3D12_RESOURCE_DIMENSION_TEXTURE2D,
Alignment: 0,
Width: width as u64,
Height: height,
DepthOrArraySize: 1,
MipLevels: 1,
Format: format,
SampleDesc: DXGI_SAMPLE_DESC {
Count: 1,
Quality: 0,
},
Layout: D3D12_TEXTURE_LAYOUT_UNKNOWN,
Flags: D3D12_RESOURCE_FLAG_ALLOW_RENDER_TARGET,
};
unsafe {
let mut resource: Option<ID3D12Resource> = None;
device.CreateCommittedResource(
&heap,
D3D12_HEAP_FLAG_SHARED,
&desc,
D3D12_RESOURCE_STATE_COMMON,
None,
&mut resource,
)?;
let resource = resource.ok_or_else(|| Error::from_hresult(E_POINTER))?;
let handle = device.CreateSharedHandle(&resource, None, GENERIC_ALL, PCWSTR::null())?;
Ok(Self {
resource,
handle,
width,
height,
format,
})
}
}
pub fn handle(&self) -> HANDLE {
self.handle
}
pub fn resource(&self) -> &ID3D12Resource {
&self.resource
}
pub fn width(&self) -> u32 {
self.width
}
pub fn height(&self) -> u32 {
self.height
}
pub fn format(&self) -> DXGI_FORMAT {
self.format
}
}
impl Drop for SharedSurface {
fn drop(&mut self) {
unsafe {
let _ = CloseHandle(self.handle);
}
}
}
pub struct Fence {
fence: ID3D12Fence,
handle: HANDLE,
value: u64,
}
impl Fence {
pub fn new(device: &ID3D12Device) -> windows::core::Result<Self> {
unsafe {
let fence: ID3D12Fence = device.CreateFence(0, D3D12_FENCE_FLAG_SHARED)?;
let handle = device.CreateSharedHandle(&fence, None, GENERIC_ALL, PCWSTR::null())?;
Ok(Self {
fence,
handle,
value: 0,
})
}
}
pub fn handle(&self) -> HANDLE {
self.handle
}
pub fn value(&self) -> u64 {
self.value
}
pub fn signal(&mut self, queue: &ID3D12CommandQueue) -> windows::core::Result<u64> {
self.value += 1;
unsafe {
queue.Signal(&self.fence, self.value)?;
}
Ok(self.value)
}
}
impl Drop for Fence {
fn drop(&mut self) {
unsafe {
let _ = CloseHandle(self.handle);
}
}
}