mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Properly wait to request buffer mapping until after the command to copy the screenshot texture to the buffer has been submitted.
This commit is contained in:
parent
b5bac97c2e
commit
adec5905bd
@ -14,6 +14,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
### Removed
|
||||
|
||||
### Fixed
|
||||
- Fixed bug that would sometimes cause taking a screenshot to panic because a buffer was mapped a the wrong time.
|
||||
|
||||
## [0.12.0] - 2022-02-19
|
||||
|
||||
|
@ -553,11 +553,11 @@ impl<'frame> Drop for Drawer<'frame> {
|
||||
// If taking a screenshot and the blit pipeline is available
|
||||
// NOTE: blit pipeline should always be available for now so we don't report an
|
||||
// error if it isn't
|
||||
if let Some((screenshot, blit)) = self
|
||||
let download_and_handle_screenshot = self
|
||||
.taking_screenshot
|
||||
.take()
|
||||
.zip(self.borrow.pipelines.blit())
|
||||
{
|
||||
.map(|(screenshot, blit)| {
|
||||
// Image needs to be copied from the screenshot texture to the swapchain texture
|
||||
let mut render_pass = encoder.scoped_render_pass(
|
||||
"screenshot blit",
|
||||
@ -579,16 +579,22 @@ impl<'frame> Drop for Drawer<'frame> {
|
||||
render_pass.set_bind_group(0, screenshot.bind_group(), &[]);
|
||||
render_pass.draw(0..3, 0..1);
|
||||
drop(render_pass);
|
||||
// Issues a command to copy from the texture to a buffer and then sends the
|
||||
// buffer off to another thread to be mapped and processed
|
||||
screenshot.download_and_handle(&mut encoder);
|
||||
}
|
||||
// Issues a command to copy from the texture to a buffer and returns a closure
|
||||
// that will send the buffer off to another thread to be mapped
|
||||
// and processed.
|
||||
screenshot.copy_to_buffer(&mut encoder)
|
||||
});
|
||||
|
||||
let (mut encoder, profiler) = encoder.end_scope();
|
||||
profiler.resolve_queries(&mut encoder);
|
||||
|
||||
// It is recommended to only do one submit per frame
|
||||
self.borrow.queue.submit(std::iter::once(encoder.finish()));
|
||||
// Need to call this after submit so the async mapping doesn't occur before
|
||||
// copying the screenshot to the buffer which will be mapped.
|
||||
if let Some(f) = download_and_handle_screenshot {
|
||||
f();
|
||||
}
|
||||
|
||||
profiler
|
||||
.end_frame()
|
||||
|
@ -88,9 +88,13 @@ impl TakeScreenshot {
|
||||
/// swapchain image
|
||||
pub fn bind_group(&self) -> &wgpu::BindGroup { &self.bind_group.bind_group }
|
||||
|
||||
/// NOTE: spawns thread
|
||||
/// Call this after rendering to the screenshot texture
|
||||
pub fn download_and_handle(self, encoder: &mut wgpu::CommandEncoder) {
|
||||
///
|
||||
/// Issues a command to copy from the texture to a buffer and returns a
|
||||
/// closure that needs to be called after submitting the encoder
|
||||
/// to the queue. When called, the closure will spawn a new thread for
|
||||
/// async mapping of the buffer and downloading of the screenshot.
|
||||
pub fn copy_to_buffer(self, encoder: &mut wgpu::CommandEncoder) -> impl FnOnce() {
|
||||
// Calculate padded bytes per row
|
||||
let padded_bytes_per_row = padded_bytes_per_row(self.width, self.bytes_per_pixel);
|
||||
// Copy image to a buffer
|
||||
@ -114,6 +118,8 @@ impl TakeScreenshot {
|
||||
depth_or_array_layers: 1,
|
||||
},
|
||||
);
|
||||
|
||||
move || {
|
||||
// Send buffer to another thread for async mapping, downloading, and passing to
|
||||
// the given handler function (which probably saves it to the disk)
|
||||
std::thread::Builder::new()
|
||||
@ -123,6 +129,7 @@ impl TakeScreenshot {
|
||||
})
|
||||
.expect("Failed to spawn screenshot thread");
|
||||
}
|
||||
}
|
||||
|
||||
fn download_and_handle_internal(self) {
|
||||
// Calculate padded bytes per row
|
||||
|
Loading…
Reference in New Issue
Block a user