rFactor2_vk_hud/src/overlay/rendering.rs

158 lines
4.5 KiB
Rust

use anyhow::Result;
use cgmath::{Vector2, Vector4};
use vulkan_rs::prelude::*;
use std::sync::{Arc, Mutex};
use super::{pipeline::SingleColorPipeline, rfactor_data::RenderObject};
use crate::write_log;
#[derive(Clone)]
pub struct PositionOnlyVertex {
pub position: Vector4<f32>,
}
impl PositionOnlyVertex {
///
/// corners[0] - bottom left
/// corners[1] - top left
/// corners[2] - top right
/// corners[3] - bottom right
///
pub fn from_2d_corners(corners: [Vector2<f32>; 4]) -> [Self; 6] {
[
Self {
position: corners[0].extend(0.0).extend(1.0),
},
Self {
position: corners[1].extend(0.0).extend(1.0),
},
Self {
position: corners[2].extend(0.0).extend(1.0),
},
Self {
position: corners[2].extend(0.0).extend(1.0),
},
Self {
position: corners[3].extend(0.0).extend(1.0),
},
Self {
position: corners[0].extend(0.0).extend(1.0),
},
]
}
}
pub struct Rendering {
swapchain: Arc<Swapchain>,
pipeline: SingleColorPipeline,
render_target: RenderTarget,
submit_info: SubmitInfo,
}
impl Rendering {
pub fn new(
device: Arc<Device>,
queue: Arc<Mutex<Queue>>,
swapchain: Arc<Swapchain>,
) -> Result<Self> {
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) {
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");
Ok(Self {
swapchain,
pipeline: SingleColorPipeline::new(device, render_target.render_pass())?,
render_target,
submit_info: SubmitInfo::default(),
})
}
pub fn swapchain(&self) -> &Arc<Swapchain> {
&self.swapchain
}
pub fn single_color_pipeline(&self) -> &SingleColorPipeline {
&self.pipeline
}
pub fn render(
&mut self,
device: Arc<Device>,
queue: Arc<Mutex<Queue>>,
swapchain: Arc<Swapchain>,
objects: &[&dyn RenderObject],
) -> Result<VkSubmitInfo> {
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 command_buffer = CommandBuffer::new_primary().build(device, queue)?;
{
let mut recorder = command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_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);
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);
}
self.submit_info = SubmitInfo::default()
.add_wait_stage(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
.add_command_buffer(command_buffer);
Ok(self.submit_info.as_vk_submit())
}
}