use anyhow::Result; use vulkan_rs::prelude::*; use std::{ sync::{Arc, Mutex}, time::Duration, }; use crate::write_log; pub struct Rendering { swapchain: Arc<Swapchain>, images: Vec<Arc<Image>>, queue: Arc<Mutex<Queue>>, render_callbacks: Vec<Box<dyn Fn(u32) -> Result<Arc<CommandBuffer>>>>, } impl Rendering { pub fn new(queue: Arc<Mutex<Queue>>, swapchain: Arc<Swapchain>) -> Result<Self> { crate::write_log!("-> Rendering ctor: begin"); let vk_images = swapchain.vk_images()?; write_log!(format!( "-> Rendering ctor: vk images ({})", vk_images.len() )); let images = match swapchain.wrap_images(&vk_images, &queue, true) { Ok(images) => images, Err(err) => { write_log!(format!("-> Rendering ctor: failed wrapper: {:?}", err)); return Err(err); } }; write_log!("-> Rendering ctor: wrapped images"); write_log!(format!( "-> Rendering swapchain extents ({}, {})", swapchain.width(), swapchain.height(), )); Ok(Self { swapchain, images, queue, render_callbacks: Vec::new(), }) } pub fn swapchain(&self) -> &Arc<Swapchain> { &self.swapchain } pub fn add_render_callback<F>(&mut self, f: F) where F: Fn(u32) -> Result<Arc<CommandBuffer>> + 'static, { self.render_callbacks.push(Box::new(f)); } pub fn render(&self) -> Result<()> { let image_index = self.swapchain.current_index(); let command_buffers: Vec<Arc<CommandBuffer>> = self .render_callbacks .iter() .map(|c| c(image_index)) .collect::<Result<Vec<Arc<CommandBuffer>>>>()?; write_log!(format!( "submitting {} commandbuffer(s)", command_buffers.len() )); let queue = self.queue.lock().unwrap(); queue.minimal_submit(Duration::from_secs(10), &command_buffers)?; Ok(()) } pub fn images(&self) -> &Vec<Arc<Image>> { &self.images } }