2024-08-23 11:22:09 +00:00
|
|
|
use crate::Result;
|
2025-02-26 13:51:44 +00:00
|
|
|
use crate::prelude::*;
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
use cgmath::{Matrix4, SquareMatrix};
|
2025-02-26 13:51:44 +00:00
|
|
|
use ecs::World;
|
2024-08-23 11:22:09 +00:00
|
|
|
use ui::prelude::*;
|
|
|
|
use vulkan_rs::prelude::*;
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
use std::marker::PhantomData;
|
2024-08-23 11:22:09 +00:00
|
|
|
use std::ops::Deref;
|
|
|
|
use std::sync::{
|
|
|
|
Arc, Mutex, RwLock,
|
2025-02-26 13:51:44 +00:00
|
|
|
atomic::{AtomicUsize, Ordering::SeqCst},
|
2024-08-23 11:22:09 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy, PartialEq)]
|
|
|
|
pub enum Eye {
|
|
|
|
Left,
|
|
|
|
Right,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Clone, Copy)]
|
|
|
|
pub struct VRTransformations {
|
|
|
|
pub proj: Matrix4<f32>,
|
|
|
|
pub view: Matrix4<f32>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl VRTransformations {
|
|
|
|
pub fn invert(self) -> Result<Self> {
|
|
|
|
Ok(VRTransformations {
|
|
|
|
proj: self
|
|
|
|
.proj
|
|
|
|
.invert()
|
|
|
|
.ok_or(anyhow::Error::msg("Could not invert Matrix"))?,
|
|
|
|
view: self
|
|
|
|
.view
|
|
|
|
.invert()
|
|
|
|
.ok_or(anyhow::Error::msg("Could not invert Matrix"))?,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Default for VRTransformations {
|
|
|
|
fn default() -> Self {
|
|
|
|
VRTransformations {
|
|
|
|
proj: Matrix4::identity(),
|
|
|
|
view: Matrix4::identity(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
pub struct RenderBackend<S: TScene + 'static> {
|
2024-08-23 11:22:09 +00:00
|
|
|
device: Arc<Device>,
|
|
|
|
queue: Arc<Mutex<Queue>>,
|
|
|
|
|
|
|
|
// driver provided images
|
|
|
|
swapchain_images: Mutex<TargetMode<Vec<Arc<Image>>>>,
|
|
|
|
image_count: AtomicUsize,
|
|
|
|
|
|
|
|
clear_color: RwLock<VkClearColorValue>,
|
|
|
|
|
|
|
|
command_buffer: Arc<CommandBuffer>,
|
|
|
|
|
|
|
|
post_processes: Mutex<Vec<Arc<dyn PostProcess>>>,
|
2025-02-26 13:51:44 +00:00
|
|
|
|
|
|
|
s: PhantomData<S>,
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
impl<S: TScene + 'static> RenderBackend<S> {
|
|
|
|
pub fn new(
|
2024-08-23 11:22:09 +00:00
|
|
|
device: &Arc<Device>,
|
|
|
|
queue: &Arc<Mutex<Queue>>,
|
|
|
|
images: TargetMode<Vec<Arc<Image>>>,
|
|
|
|
) -> Result<Self> {
|
|
|
|
let image_count = match &images {
|
|
|
|
TargetMode::Mono(images) => images.len(),
|
|
|
|
TargetMode::Stereo(left_images, right_images) => {
|
|
|
|
debug_assert!(left_images.len() == right_images.len());
|
|
|
|
left_images.len()
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// create a new command buffer
|
|
|
|
let command_buffer = CommandBuffer::new_primary().build(device.clone(), queue.clone())?;
|
|
|
|
|
|
|
|
Ok(RenderBackend {
|
|
|
|
device: device.clone(),
|
|
|
|
queue: queue.clone(),
|
|
|
|
|
|
|
|
swapchain_images: Mutex::new(images),
|
|
|
|
image_count: AtomicUsize::new(image_count),
|
|
|
|
|
|
|
|
clear_color: RwLock::new(VkClearColorValue::float32([0.0, 0.0, 0.0, 1.0])),
|
|
|
|
|
|
|
|
command_buffer,
|
|
|
|
|
|
|
|
post_processes: Mutex::new(Vec::new()),
|
2025-02-26 13:51:44 +00:00
|
|
|
|
|
|
|
s: PhantomData,
|
2024-08-23 11:22:09 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn required_image_usage() -> VkImageUsageFlagBits {
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
impl<S: TScene + 'static> RenderBackend<S> {
|
2024-08-23 11:22:09 +00:00
|
|
|
pub fn device(&self) -> &Arc<Device> {
|
|
|
|
&self.device
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn queue(&self) -> &Arc<Mutex<Queue>> {
|
|
|
|
&self.queue
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn set_clear_color(&self, clear_color: [f32; 4]) {
|
|
|
|
*self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color);
|
|
|
|
}
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
pub fn render(
|
|
|
|
&mut self,
|
|
|
|
world: &mut World,
|
|
|
|
image_indices: TargetMode<usize>,
|
|
|
|
) -> Result<&Arc<CommandBuffer>> {
|
2024-08-23 11:22:09 +00:00
|
|
|
// begin main command buffer
|
|
|
|
let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new(
|
|
|
|
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
|
|
|
|
))?;
|
|
|
|
|
|
|
|
// clear the current swapchain image
|
|
|
|
{
|
|
|
|
let swapchain_images = self.swapchain_images.lock().unwrap();
|
|
|
|
let target_layout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
|
|
|
|
let clear_color = self.clear_color.read().unwrap().clone();
|
|
|
|
|
|
|
|
match (&image_indices, swapchain_images.deref()) {
|
|
|
|
(TargetMode::Mono(image_index), TargetMode::Mono(images)) => {
|
|
|
|
let swapchain_image = &images[*image_index];
|
|
|
|
|
|
|
|
Self::clear_image(
|
|
|
|
&mut buffer_recorder,
|
|
|
|
swapchain_image,
|
|
|
|
clear_color,
|
|
|
|
target_layout,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
(
|
|
|
|
TargetMode::Stereo(left_image_index, right_image_index),
|
|
|
|
TargetMode::Stereo(left_images, right_images),
|
|
|
|
) => {
|
|
|
|
let left_image = &left_images[*left_image_index];
|
|
|
|
let right_image = &right_images[*right_image_index];
|
|
|
|
|
|
|
|
Self::clear_image(
|
|
|
|
&mut buffer_recorder,
|
|
|
|
left_image,
|
|
|
|
clear_color.clone(),
|
|
|
|
target_layout,
|
|
|
|
);
|
|
|
|
|
|
|
|
Self::clear_image(
|
|
|
|
&mut buffer_recorder,
|
|
|
|
right_image,
|
|
|
|
clear_color,
|
|
|
|
target_layout,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => panic!("Expected another target mode"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// make a call to the connected scene
|
2025-02-27 13:14:29 +00:00
|
|
|
world.resources.get_mut_unchecked::<S>().process(
|
2024-08-23 11:22:09 +00:00
|
|
|
&mut buffer_recorder,
|
|
|
|
&*self.swapchain_images.lock().unwrap(),
|
|
|
|
&image_indices,
|
2025-02-27 13:14:29 +00:00
|
|
|
world,
|
2024-08-23 11:22:09 +00:00
|
|
|
)?;
|
|
|
|
|
|
|
|
// post processing
|
|
|
|
for post_process in self.post_processes.lock().unwrap().iter() {
|
|
|
|
post_process.process(&mut buffer_recorder, &image_indices)?;
|
|
|
|
}
|
|
|
|
|
|
|
|
Ok(&self.command_buffer)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn resize(
|
|
|
|
&mut self,
|
2025-02-26 13:51:44 +00:00
|
|
|
world: &mut World,
|
2024-08-23 11:22:09 +00:00
|
|
|
images: TargetMode<Vec<Arc<Image>>>,
|
|
|
|
width: u32,
|
|
|
|
height: u32,
|
|
|
|
) -> Result<()> {
|
|
|
|
self.image_count.store(
|
|
|
|
match &images {
|
|
|
|
TargetMode::Mono(images) => images.len(),
|
|
|
|
TargetMode::Stereo(left_images, right_images) => {
|
|
|
|
debug_assert!(left_images.len() == right_images.len());
|
|
|
|
left_images.len()
|
|
|
|
}
|
|
|
|
},
|
|
|
|
SeqCst,
|
|
|
|
);
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
world
|
|
|
|
.resources
|
|
|
|
.get_mut::<S>()
|
|
|
|
.resize(width as f32, height as f32, &images)?;
|
2024-08-23 11:22:09 +00:00
|
|
|
*self.swapchain_images.lock().unwrap() = images;
|
|
|
|
|
|
|
|
for post_process in self.post_processes.lock().unwrap().iter() {
|
2024-08-27 09:43:48 +00:00
|
|
|
post_process.resize(width, height, &*self.swapchain_images.lock().unwrap())?;
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn add_post_processing_routine(&self, post_process: Arc<dyn PostProcess>) {
|
|
|
|
let mut post_processes = self.post_processes.lock().unwrap();
|
|
|
|
|
|
|
|
// only add if it isn't present already
|
|
|
|
if post_processes
|
|
|
|
.iter()
|
|
|
|
.find(|p| Arc::ptr_eq(p, &post_process))
|
|
|
|
.is_none()
|
|
|
|
{
|
|
|
|
post_processes.push(post_process);
|
|
|
|
|
|
|
|
post_processes.sort_by(|lhs, rhs| lhs.priority().cmp(&rhs.priority()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn remove_post_processing_routine(&self, post_process: Arc<dyn PostProcess>) {
|
|
|
|
let mut post_processes = self.post_processes.lock().unwrap();
|
|
|
|
|
|
|
|
if let Some(index) = post_processes
|
|
|
|
.iter()
|
|
|
|
.position(|p| Arc::ptr_eq(p, &post_process))
|
|
|
|
{
|
|
|
|
post_processes.remove(index);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn clear_post_processing_routines(&self) {
|
|
|
|
self.post_processes.lock().unwrap().clear();
|
|
|
|
}
|
|
|
|
|
|
|
|
// getter
|
|
|
|
pub fn image_count(&self) -> usize {
|
|
|
|
self.image_count.load(SeqCst)
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn images(&self) -> TargetMode<Vec<Arc<Image>>> {
|
|
|
|
self.swapchain_images.lock().unwrap().clone()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-26 13:51:44 +00:00
|
|
|
impl<S: TScene + 'static> RenderBackend<S> {
|
2024-08-23 11:22:09 +00:00
|
|
|
#[inline]
|
|
|
|
fn clear_image(
|
|
|
|
buffer_recorder: &mut CommandBufferRecorder<'_>,
|
|
|
|
image: &Arc<Image>,
|
|
|
|
clear_color: VkClearColorValue,
|
|
|
|
target_layout: VkImageLayout,
|
|
|
|
) {
|
|
|
|
buffer_recorder.set_full_image_layout(image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
|
|
|
|
buffer_recorder.clear_color_image(image, clear_color);
|
|
|
|
buffer_recorder.set_full_image_layout(image, target_layout);
|
|
|
|
}
|
|
|
|
}
|