use anyhow::Result; use cgmath::{Matrix4, Vector2, Vector4}; use vulkan_rs::prelude::*; use std::{ sync::{Arc, Mutex}, time::Duration, }; use super::{pipeline::SingleColorPipeline, rfactor_data::RenderObject}; use crate::write_log; #[derive(Clone)] pub struct PositionOnlyVertex { pub position: Vector4, } impl PositionOnlyVertex { /// /// corners[0] - bottom left /// corners[1] - top left /// corners[2] - top right /// corners[3] - bottom right /// pub fn from_2d_corners(ortho: Matrix4, corners: [Vector2; 4]) -> [Self; 6] { [ Self { position: ortho * corners[0].extend(0.0).extend(1.0), }, Self { position: ortho * corners[1].extend(0.0).extend(1.0), }, Self { position: ortho * corners[2].extend(0.0).extend(1.0), }, Self { position: ortho * corners[2].extend(0.0).extend(1.0), }, Self { position: ortho * corners[3].extend(0.0).extend(1.0), }, Self { position: ortho * corners[0].extend(0.0).extend(1.0), }, ] } } pub struct Rendering { swapchain: Arc, pipeline: SingleColorPipeline, render_target: RenderTarget, command_buffer: Arc, queue: Arc>, } impl Rendering { pub fn new( device: Arc, queue: Arc>, swapchain: Arc, ) -> Result { 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"); let render_target = RenderTarget::builder() .add_sub_pass( SubPass::builder(swapchain.width(), swapchain.height()) .set_prepared_targets(&images, 0, [0.0, 0.0, 0.0, 1.0], false) .build(&device, &queue)?, ) .build(&device)?; write_log!("-> Rendering ctor: created render_target"); write_log!(format!( "-> Rendering swapchain extents ({}, {})", swapchain.width(), swapchain.height(), )); Ok(Self { swapchain, pipeline: SingleColorPipeline::new(device.clone(), render_target.render_pass())?, render_target, command_buffer: CommandBuffer::new_primary().build(device.clone(), queue.clone())?, queue, }) } pub fn swapchain(&self) -> &Arc { &self.swapchain } pub fn single_color_pipeline(&self) -> &SingleColorPipeline { &self.pipeline } pub fn render( &mut self, swapchain: Arc, objects: &[&dyn RenderObject], ) -> Result<()> { let image_index = self.swapchain.current_index(); let viewport = [VkViewport { x: 0.0, y: 0.0, width: swapchain.width() as f32, height: swapchain.height() as f32, minDepth: 0.0, maxDepth: 1.0, }]; let scissor = [VkRect2D { offset: VkOffset2D { x: 0, y: 0 }, extent: VkExtent2D { width: swapchain.width(), height: swapchain.height(), }, }]; { let mut recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new( VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, ))?; self.render_target .begin(&recorder, VK_SUBPASS_CONTENTS_INLINE, image_index as usize); recorder.bind_pipeline(self.pipeline.pipeline())?; recorder.set_scissor(&scissor); recorder.set_viewport(&viewport); write_log!(format!("-> Rendering {} objects", objects.len())); for object in objects { let buffer = object.buffer(); recorder.bind_descriptor_sets_minimal(&[object.descriptor()]); recorder.bind_vertex_buffer(buffer); recorder.draw_complete_single_instance(buffer.size() as u32); } self.render_target.end(&recorder); } let queue = self.queue.lock().unwrap(); queue.minimal_submit(Duration::from_secs(10), &[self.command_buffer.clone()])?; Ok(()) } }