use std::mem::ManuallyDrop;
use windows::Win32::Graphics::Direct3D12::*;
fn assert_sync_access_pairing(sync: D3D12_BARRIER_SYNC, access: D3D12_BARRIER_ACCESS, label: &str) {
if sync == D3D12_BARRIER_SYNC_NONE {
assert!(
access == D3D12_BARRIER_ACCESS_NO_ACCESS,
"{label}: SYNC_NONE requires ACCESS_NO_ACCESS, got access {:#x}",
access.0,
);
}
if access == D3D12_BARRIER_ACCESS_NO_ACCESS {
assert!(
sync == D3D12_BARRIER_SYNC_NONE,
"{label}: ACCESS_NO_ACCESS requires SYNC_NONE, got sync {:#x}",
sync.0,
);
}
}
pub const BUFFER_BARRIER_FULL_SIZE: u64 = u64::MAX;
pub unsafe fn barrier_buffers(cmd: &ID3D12GraphicsCommandList7, barriers: &[D3D12_BUFFER_BARRIER]) {
if barriers.is_empty() {
return;
}
let group = D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_BUFFER,
NumBarriers: barriers.len() as u32,
Anonymous: D3D12_BARRIER_GROUP_0 {
pBufferBarriers: barriers.as_ptr(),
},
};
cmd.Barrier(&[group]);
}
pub unsafe fn barrier_groups(
cmd: &ID3D12GraphicsCommandList7,
buffers: &[D3D12_BUFFER_BARRIER],
textures: &[D3D12_TEXTURE_BARRIER],
) {
let mut groups: [D3D12_BARRIER_GROUP; 2] = [
D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_BUFFER,
NumBarriers: 0,
Anonymous: D3D12_BARRIER_GROUP_0 {
pBufferBarriers: std::ptr::null(),
},
},
D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_TEXTURE,
NumBarriers: 0,
Anonymous: D3D12_BARRIER_GROUP_0 {
pTextureBarriers: std::ptr::null(),
},
},
];
let mut count = 0usize;
if !buffers.is_empty() {
groups[count] = D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_BUFFER,
NumBarriers: buffers.len() as u32,
Anonymous: D3D12_BARRIER_GROUP_0 {
pBufferBarriers: buffers.as_ptr(),
},
};
count += 1;
}
if !textures.is_empty() {
groups[count] = D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_TEXTURE,
NumBarriers: textures.len() as u32,
Anonymous: D3D12_BARRIER_GROUP_0 {
pTextureBarriers: textures.as_ptr(),
},
};
count += 1;
}
if count == 0 {
return;
}
cmd.Barrier(&groups[..count]);
}
pub unsafe fn barrier_textures(cmd: &ID3D12GraphicsCommandList7, barriers: &[D3D12_TEXTURE_BARRIER]) {
if barriers.is_empty() {
return;
}
let group = D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_TEXTURE,
NumBarriers: barriers.len() as u32,
Anonymous: D3D12_BARRIER_GROUP_0 {
pTextureBarriers: barriers.as_ptr(),
},
};
cmd.Barrier(&[group]);
}
pub unsafe fn barrier_globals(cmd: &ID3D12GraphicsCommandList7, barriers: &[D3D12_GLOBAL_BARRIER]) {
if barriers.is_empty() {
return;
}
let group = D3D12_BARRIER_GROUP {
Type: D3D12_BARRIER_TYPE_GLOBAL,
NumBarriers: barriers.len() as u32,
Anonymous: D3D12_BARRIER_GROUP_0 {
pGlobalBarriers: barriers.as_ptr(),
},
};
cmd.Barrier(&[group]);
}
pub unsafe fn drop_texture_barriers(barriers: &mut [D3D12_TEXTURE_BARRIER]) {
for b in barriers {
ManuallyDrop::drop(&mut b.pResource);
}
}
pub unsafe fn drop_buffer_barriers(barriers: &mut [D3D12_BUFFER_BARRIER]) {
for b in barriers {
ManuallyDrop::drop(&mut b.pResource);
}
}
pub fn texture_subresource_all() -> D3D12_BARRIER_SUBRESOURCE_RANGE {
D3D12_BARRIER_SUBRESOURCE_RANGE {
IndexOrFirstMipLevel: 0xffffffff,
NumMipLevels: 0,
FirstArraySlice: 0,
NumArraySlices: 0,
FirstPlane: 0,
NumPlanes: 0,
}
}
pub fn buffer_barrier_full(
resource: &ID3D12Resource,
sync_before: D3D12_BARRIER_SYNC,
sync_after: D3D12_BARRIER_SYNC,
access_before: D3D12_BARRIER_ACCESS,
access_after: D3D12_BARRIER_ACCESS,
) -> D3D12_BUFFER_BARRIER {
assert_sync_access_pairing(sync_before, access_before, "buffer SyncBefore/AccessBefore");
assert_sync_access_pairing(sync_after, access_after, "buffer SyncAfter/AccessAfter");
D3D12_BUFFER_BARRIER {
SyncBefore: sync_before,
SyncAfter: sync_after,
AccessBefore: access_before,
AccessAfter: access_after,
pResource: ManuallyDrop::new(Some(resource.clone())),
Offset: 0,
Size: BUFFER_BARRIER_FULL_SIZE,
}
}
pub fn texture_barrier_full(
resource: &ID3D12Resource,
sync_before: D3D12_BARRIER_SYNC,
sync_after: D3D12_BARRIER_SYNC,
access_before: D3D12_BARRIER_ACCESS,
access_after: D3D12_BARRIER_ACCESS,
layout_before: D3D12_BARRIER_LAYOUT,
layout_after: D3D12_BARRIER_LAYOUT,
) -> D3D12_TEXTURE_BARRIER {
assert_sync_access_pairing(sync_before, access_before, "texture SyncBefore/AccessBefore");
assert_sync_access_pairing(sync_after, access_after, "texture SyncAfter/AccessAfter");
D3D12_TEXTURE_BARRIER {
SyncBefore: sync_before,
SyncAfter: sync_after,
AccessBefore: access_before,
AccessAfter: access_after,
LayoutBefore: layout_before,
LayoutAfter: layout_after,
pResource: ManuallyDrop::new(Some(resource.clone())),
Subresources: texture_subresource_all(),
Flags: D3D12_TEXTURE_BARRIER_FLAG_NONE,
}
}