rt(mtl): fix history buffer off-by-one by buffering the history read.
This commit is contained in:
parent
98d8d91c66
commit
02288554b9
|
@ -66,6 +66,14 @@ pub struct FilterChainMetal {
|
||||||
output_framebuffers: Box<[OwnedTexture]>,
|
output_framebuffers: Box<[OwnedTexture]>,
|
||||||
feedback_framebuffers: Box<[OwnedTexture]>,
|
feedback_framebuffers: Box<[OwnedTexture]>,
|
||||||
history_framebuffers: VecDeque<OwnedTexture>,
|
history_framebuffers: VecDeque<OwnedTexture>,
|
||||||
|
/// Metal does not allow us to push the input texture to history
|
||||||
|
/// before recording framebuffers, so we double-buffer it.
|
||||||
|
///
|
||||||
|
/// First we swap OriginalHistory1 with the contents of this buffer (which were written to
|
||||||
|
/// in the previous frame)
|
||||||
|
///
|
||||||
|
/// Then we blit the original to the buffer.
|
||||||
|
prev_frame_history_buffer: OwnedTexture,
|
||||||
disable_mipmaps: bool,
|
disable_mipmaps: bool,
|
||||||
default_options: FrameOptionsMetal,
|
default_options: FrameOptionsMetal,
|
||||||
}
|
}
|
||||||
|
@ -206,7 +214,18 @@ impl FilterChainMetal {
|
||||||
cmd: &ProtocolObject<dyn MTLCommandBuffer>,
|
cmd: &ProtocolObject<dyn MTLCommandBuffer>,
|
||||||
input: &ProtocolObject<dyn MTLTexture>,
|
input: &ProtocolObject<dyn MTLTexture>,
|
||||||
) -> error::Result<()> {
|
) -> error::Result<()> {
|
||||||
if let Some(mut back) = self.history_framebuffers.pop_back() {
|
// If there's no history, there's no need to do any of this.
|
||||||
|
let Some(mut back) = self.history_framebuffers.pop_back() else {
|
||||||
|
return Ok(());
|
||||||
|
};
|
||||||
|
|
||||||
|
// Push the previous frame as OriginalHistory1
|
||||||
|
std::mem::swap(&mut back, &mut self.prev_frame_history_buffer);
|
||||||
|
self.history_framebuffers.push_front(back);
|
||||||
|
|
||||||
|
// Copy the current frame into prev_frame_history_buffer, which will be
|
||||||
|
// pushed to OriginalHistory1 in the next frame.
|
||||||
|
let back = &mut self.prev_frame_history_buffer;
|
||||||
let mipmapper = cmd
|
let mipmapper = cmd
|
||||||
.blitCommandEncoder()
|
.blitCommandEncoder()
|
||||||
.ok_or(FilterChainError::FailedToCreateCommandBuffer)?;
|
.ok_or(FilterChainError::FailedToCreateCommandBuffer)?;
|
||||||
|
@ -220,15 +239,13 @@ impl FilterChainMetal {
|
||||||
};
|
};
|
||||||
|
|
||||||
let _old_back = std::mem::replace(
|
let _old_back = std::mem::replace(
|
||||||
&mut back,
|
back,
|
||||||
OwnedTexture::new(&self.common.device, size, 1, input.pixelFormat())?,
|
OwnedTexture::new(&self.common.device, size, 1, input.pixelFormat())?,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
back.copy_from(&mipmapper, input)?;
|
back.copy_from(&mipmapper, input)?;
|
||||||
mipmapper.endEncoding();
|
mipmapper.endEncoding();
|
||||||
self.history_framebuffers.push_front(back);
|
|
||||||
}
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -290,6 +307,8 @@ impl FilterChainMetal {
|
||||||
// initialize history
|
// initialize history
|
||||||
let (history_framebuffers, history_textures) = framebuffer_init.init_history()?;
|
let (history_framebuffers, history_textures) = framebuffer_init.init_history()?;
|
||||||
|
|
||||||
|
let history_buffer = framebuffer_gen()?;
|
||||||
|
|
||||||
let draw_quad = DrawQuad::new(&device)?;
|
let draw_quad = DrawQuad::new(&device)?;
|
||||||
Ok(FilterChainMetal {
|
Ok(FilterChainMetal {
|
||||||
common: FilterCommon {
|
common: FilterCommon {
|
||||||
|
@ -306,6 +325,7 @@ impl FilterChainMetal {
|
||||||
output_framebuffers,
|
output_framebuffers,
|
||||||
feedback_framebuffers,
|
feedback_framebuffers,
|
||||||
history_framebuffers,
|
history_framebuffers,
|
||||||
|
prev_frame_history_buffer: history_buffer,
|
||||||
disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false),
|
disable_mipmaps: options.map(|f| f.force_no_mipmaps).unwrap_or(false),
|
||||||
default_options: Default::default(),
|
default_options: Default::default(),
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in a new issue