Make fences mutable

Change the interface for fences to accept mutable references. This will
actualy help the Metal backend more than dx12 (avoiding interior
mutability) but more accurately captures intent and matches gfx-hal.
This commit is contained in:
Raph Levien 2021-05-27 15:37:05 -07:00
parent 37de07f670
commit b6292c644f
7 changed files with 49 additions and 31 deletions

View file

@ -73,7 +73,7 @@ fn toy() -> Result<(), Error> {
let pipeline = device.create_simple_compute_pipeline(SHADER_CODE, 1, 1)?; let pipeline = device.create_simple_compute_pipeline(SHADER_CODE, 1, 1)?;
let ds = device.create_descriptor_set(&pipeline, &[&dev_buf], &[&img])?; let ds = device.create_descriptor_set(&pipeline, &[&dev_buf], &[&img])?;
let mut cmd_buf = device.create_cmd_buf()?; let mut cmd_buf = device.create_cmd_buf()?;
let fence = device.create_fence(false)?; let mut fence = device.create_fence(false)?;
cmd_buf.begin(); cmd_buf.begin();
cmd_buf.copy_buffer(&buf, &dev_buf); cmd_buf.copy_buffer(&buf, &dev_buf);
cmd_buf.memory_barrier(); cmd_buf.memory_barrier();
@ -86,8 +86,8 @@ fn toy() -> Result<(), Error> {
cmd_buf.finish_timestamps(&query_pool); cmd_buf.finish_timestamps(&query_pool);
cmd_buf.host_barrier(); cmd_buf.host_barrier();
cmd_buf.finish(); cmd_buf.finish();
device.run_cmd_bufs(&[&cmd_buf], &[], &[], Some(&fence))?; device.run_cmd_bufs(&[&cmd_buf], &[], &[], Some(&mut fence))?;
device.wait_and_reset(&[&fence])?; device.wait_and_reset(&[&mut fence])?;
let mut readback: Vec<u32> = vec![0u32; 256]; let mut readback: Vec<u32> = vec![0u32; 256];
device.read_buffer(&buf, readback.as_mut_ptr() as *mut u8, 0, 1024)?; device.read_buffer(&buf, readback.as_mut_ptr() as *mut u8, 0, 1024)?;
println!("{:?}", readback); println!("{:?}", readback);

View file

@ -348,7 +348,7 @@ impl crate::Device for Dx12Device {
cmd_bufs: &[&Self::CmdBuf], cmd_bufs: &[&Self::CmdBuf],
_wait_semaphores: &[&Self::Semaphore], _wait_semaphores: &[&Self::Semaphore],
_signal_semaphores: &[&Self::Semaphore], _signal_semaphores: &[&Self::Semaphore],
fence: Option<&Self::Fence>, fence: Option<&mut Self::Fence>,
) -> Result<(), Error> { ) -> Result<(), Error> {
// TODO: handle semaphores // TODO: handle semaphores
let lists = cmd_bufs let lists = cmd_bufs
@ -405,7 +405,7 @@ impl crate::Device for Dx12Device {
Ok(Fence { fence, event, val }) Ok(Fence { fence, event, val })
} }
unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error> { unsafe fn wait_and_reset(&self, fences: &[&mut Self::Fence]) -> Result<(), Error> {
for fence in fences { for fence in fences {
// TODO: probably handle errors here. // TODO: probably handle errors here.
let _status = fence.event.wait(winapi::um::winbase::INFINITE); let _status = fence.event.wait(winapi::um::winbase::INFINITE);

View file

@ -124,9 +124,9 @@ impl Session {
let mut i = 0; let mut i = 0;
while i < pending.len() { while i < pending.len() {
if let Ok(true) = self.0.device.get_fence_status(&pending[i].fence) { if let Ok(true) = self.0.device.get_fence_status(&pending[i].fence) {
let item = pending.swap_remove(i); let mut item = pending.swap_remove(i);
// TODO: wait is superfluous, can just reset // TODO: wait is superfluous, can just reset
let _ = self.0.device.wait_and_reset(&[&item.fence]); let _ = self.0.device.wait_and_reset(vec![&mut item.fence]);
let mut pool = self.0.cmd_buf_pool.lock().unwrap(); let mut pool = self.0.cmd_buf_pool.lock().unwrap();
pool.push((item.cmd_buf, item.fence)); pool.push((item.cmd_buf, item.fence));
std::mem::drop(item.resources); std::mem::drop(item.resources);
@ -143,7 +143,7 @@ impl Session {
pub unsafe fn run_cmd_buf( pub unsafe fn run_cmd_buf(
&self, &self,
cmd_buf: CmdBuf, mut cmd_buf: CmdBuf,
wait_semaphores: &[&Semaphore], wait_semaphores: &[&Semaphore],
signal_semaphores: &[&Semaphore], signal_semaphores: &[&Semaphore],
) -> Result<SubmittedCmdBuf, Error> { ) -> Result<SubmittedCmdBuf, Error> {
@ -162,7 +162,7 @@ impl Session {
&cmd_bufs, &cmd_bufs,
wait_semaphores, wait_semaphores,
signal_semaphores, signal_semaphores,
Some(&cmd_buf.fence), Some(&mut cmd_buf.fence),
)?; )?;
Ok(SubmittedCmdBuf( Ok(SubmittedCmdBuf(
Some(SubmittedCmdBufInner { Some(SubmittedCmdBufInner {
@ -313,10 +313,10 @@ impl CmdBuf {
impl SubmittedCmdBuf { impl SubmittedCmdBuf {
pub fn wait(mut self) -> Result<(), Error> { pub fn wait(mut self) -> Result<(), Error> {
let item = self.0.take().unwrap(); let mut item = self.0.take().unwrap();
if let Some(session) = Weak::upgrade(&self.1) { if let Some(session) = Weak::upgrade(&self.1) {
unsafe { unsafe {
session.device.wait_and_reset(&[&item.fence])?; session.device.wait_and_reset(vec![&mut item.fence])?;
} }
session session
.cmd_buf_pool .cmd_buf_pool

View file

@ -194,7 +194,7 @@ pub trait Device: Sized {
cmd_buf: &[&Self::CmdBuf], cmd_buf: &[&Self::CmdBuf],
wait_semaphores: &[&Self::Semaphore], wait_semaphores: &[&Self::Semaphore],
signal_semaphores: &[&Self::Semaphore], signal_semaphores: &[&Self::Semaphore],
fence: Option<&Self::Fence>, fence: Option<&mut Self::Fence>,
) -> Result<(), Error>; ) -> Result<(), Error>;
/// Copy data from the buffer to memory. /// Copy data from the buffer to memory.
@ -231,7 +231,7 @@ pub trait Device: Sized {
unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error>; unsafe fn create_semaphore(&self) -> Result<Self::Semaphore, Error>;
unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error>; unsafe fn create_fence(&self, signaled: bool) -> Result<Self::Fence, Error>;
unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error>; unsafe fn wait_and_reset(&self, fences: &[&mut Self::Fence]) -> Result<(), Error>;
unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result<bool, Error>; unsafe fn get_fence_status(&self, fence: &Self::Fence) -> Result<bool, Error>;
unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Self::Sampler, Error>; unsafe fn create_sampler(&self, params: SamplerParams) -> Result<Self::Sampler, Error>;

View file

@ -51,6 +51,16 @@ macro_rules! mux_enum {
} }
} }
} }
$crate::mux_cfg! {
#[cfg(vk)]
#[allow(unused)]
fn vk_mut(&mut self) -> &mut $vk {
match self {
$name::Vk(x) => x,
_ => panic!("downcast error")
}
}
}
$crate::mux_cfg! { $crate::mux_cfg! {
#[cfg(dx12)] #[cfg(dx12)]
@ -62,6 +72,16 @@ macro_rules! mux_enum {
} }
} }
} }
$crate::mux_cfg! {
#[cfg(dx12)]
#[allow(unused)]
fn dx12_mut(&mut self) -> &mut $dx12 {
match self {
$name::Dx12(x) => x,
_ => panic!("downcast error")
}
}
}
} }
}; };
} }

View file

@ -197,23 +197,22 @@ impl Device {
} }
} }
pub unsafe fn wait_and_reset(&self, fences: &[&Fence]) -> Result<(), Error> { // Consider changing Vec to iterator (as is done in gfx-hal)
pub unsafe fn wait_and_reset(&self, fences: Vec<&mut Fence>) -> Result<(), Error> {
mux_match! { self; mux_match! { self;
Device::Vk(d) => { Device::Vk(d) => {
let fences = fences let mut fences = fences
.iter() .into_iter()
.copied() .map(|f| f.vk_mut())
.map(Fence::vk)
.collect::<SmallVec<[_; 4]>>(); .collect::<SmallVec<[_; 4]>>();
d.wait_and_reset(&*fences) d.wait_and_reset(&mut fences)
} }
Device::Dx12(d) => { Device::Dx12(d) => {
let fences = fences let mut fences = fences
.iter() .into_iter()
.copied() .map(|f| f.dx12_mut())
.map(Fence::dx12)
.collect::<SmallVec<[_; 4]>>(); .collect::<SmallVec<[_; 4]>>();
d.wait_and_reset(&*fences) d.wait_and_reset(&mut fences)
} }
} }
} }
@ -272,7 +271,7 @@ impl Device {
cmd_bufs: &[&CmdBuf], cmd_bufs: &[&CmdBuf],
wait_semaphores: &[&Semaphore], wait_semaphores: &[&Semaphore],
signal_semaphores: &[&Semaphore], signal_semaphores: &[&Semaphore],
fence: Option<&Fence>, fence: Option<&mut Fence>,
) -> Result<(), Error> { ) -> Result<(), Error> {
mux_match! { self; mux_match! { self;
Device::Vk(d) => d.run_cmd_bufs( Device::Vk(d) => d.run_cmd_bufs(
@ -290,7 +289,7 @@ impl Device {
.copied() .copied()
.map(Semaphore::vk) .map(Semaphore::vk)
.collect::<SmallVec<[_; 4]>>(), .collect::<SmallVec<[_; 4]>>(),
fence.map(Fence::vk), fence.map(Fence::vk_mut),
), ),
Device::Dx12(d) => d.run_cmd_bufs( Device::Dx12(d) => d.run_cmd_bufs(
&cmd_bufs &cmd_bufs
@ -307,7 +306,7 @@ impl Device {
.copied() .copied()
.map(Semaphore::dx12) .map(Semaphore::dx12)
.collect::<SmallVec<[_; 4]>>(), .collect::<SmallVec<[_; 4]>>(),
fence.map(Fence::dx12), fence.map(Fence::dx12_mut),
), ),
} }
} }

View file

@ -619,12 +619,11 @@ impl crate::Device for VkDevice {
Ok(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?) Ok(device.create_semaphore(&vk::SemaphoreCreateInfo::default(), None)?)
} }
unsafe fn wait_and_reset(&self, fences: &[&Self::Fence]) -> Result<(), Error> { unsafe fn wait_and_reset(&self, fences: &[&mut Self::Fence]) -> Result<(), Error> {
let device = &self.device.device; let device = &self.device.device;
let fences = fences let fences = fences
.iter() .iter()
.copied() .map(|f| **f)
.copied()
.collect::<SmallVec<[_; 4]>>(); .collect::<SmallVec<[_; 4]>>();
device.wait_for_fences(&fences, true, !0)?; device.wait_for_fences(&fences, true, !0)?;
device.reset_fences(&fences)?; device.reset_fences(&fences)?;
@ -718,7 +717,7 @@ impl crate::Device for VkDevice {
cmd_bufs: &[&CmdBuf], cmd_bufs: &[&CmdBuf],
wait_semaphores: &[&Self::Semaphore], wait_semaphores: &[&Self::Semaphore],
signal_semaphores: &[&Self::Semaphore], signal_semaphores: &[&Self::Semaphore],
fence: Option<&Self::Fence>, fence: Option<&mut Self::Fence>,
) -> Result<(), Error> { ) -> Result<(), Error> {
let device = &self.device.device; let device = &self.device.device;