aboutsummaryrefslogtreecommitdiff
path: root/src/systems.rs
diff options
context:
space:
mode:
authorLibravatar Silas Bartha <[email protected]>2024-04-24 21:05:55 -0400
committerLibravatar Silas Bartha <[email protected]>2024-04-24 21:05:55 -0400
commit98d21d244bb92a1a8d35b1dff35d9c10bdcab19a (patch)
tree8d1729071750d879ca2123e69df2c6bfbf1857c5 /src/systems.rs
Render Texture Extraction
Diffstat (limited to 'src/systems.rs')
-rw-r--r--src/systems.rs65
1 files changed, 65 insertions, 0 deletions
diff --git a/src/systems.rs b/src/systems.rs
new file mode 100644
index 0000000..25b25dc
--- /dev/null
+++ b/src/systems.rs
@@ -0,0 +1,65 @@
+use std::time::Duration;
+
+use bevy::{prelude::*, render::{render_asset::{RenderAssets, RenderAssetUsages}, renderer::RenderDevice, render_resource::{MapMode, Maintain, Extent3d, TextureDimension}}};
+
+use pollster::FutureExt;
+
+use crate::{render_assets::FramebufferExtractSource, components::FramebufferExtractDestination};
+
+pub fn extract_framebuffers(
+ mut extract_bundles: Query<(&Handle<FramebufferExtractSource>, &mut FramebufferExtractDestination)>,
+ sources: Res<RenderAssets<FramebufferExtractSource>>,
+ device: Res<RenderDevice>,
+) {
+ for (source_handle, destination_handle) in extract_bundles.iter_mut() {
+ let Some(gpu_source) = sources.get(source_handle) else {
+ continue;
+ };
+
+ let mut image_bytes = {
+ let slice = gpu_source.buffer.slice(..);
+
+ {
+ let (tx, rx) = oneshot::channel();
+ device.map_buffer(&slice, MapMode::Read, move |res| {
+ tx.send(res).unwrap();
+ });
+ device.poll(Maintain::Wait);
+ rx.block_on().unwrap().unwrap();
+ }
+
+ slice.get_mapped_range().to_vec()
+ };
+
+ gpu_source.buffer.unmap();
+
+ let bytes_per_row = gpu_source.bytes_per_row as usize;
+ let padded_bytes_per_row = gpu_source.padded_bytes_per_row as usize;
+ let source_size = gpu_source.source_size;
+ let destination_handle = destination_handle.clone();
+ let source_format = gpu_source.format;
+
+ std::thread::spawn(move || {
+ if bytes_per_row != padded_bytes_per_row {
+ let mut unpadded_bytes = Vec::<u8>::with_capacity(source_size.height as usize * bytes_per_row);
+ for padded_row in image_bytes.chunks(padded_bytes_per_row) {
+ unpadded_bytes.extend_from_slice(&padded_row[..bytes_per_row]);
+ }
+ image_bytes = unpadded_bytes;
+ }
+
+ *destination_handle.0.lock().unwrap() = Image::new(
+ Extent3d {
+ width: source_size.width,
+ height: source_size.height,
+ depth_or_array_layers: 1,
+ },
+ TextureDimension::D2,
+ image_bytes,
+ source_format,
+ RenderAssetUsages::MAIN_WORLD | RenderAssetUsages::RENDER_WORLD,
+ );
+ });
+ }
+
+}