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-28 15:41:59 +00:00
|
|
|
use std::any::TypeId;
|
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-03-01 05:01:46 +00:00
|
|
|
struct SceneHandle {
|
|
|
|
type_id: TypeId,
|
|
|
|
priority: u32,
|
|
|
|
|
|
|
|
render: Box<
|
|
|
|
dyn FnMut(
|
|
|
|
&mut CommandBufferRecorder<'_>,
|
|
|
|
&TargetMode<Vec<Arc<Image>>>,
|
|
|
|
&TargetMode<usize>,
|
|
|
|
&mut World,
|
|
|
|
) -> Result<()>
|
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ 'static,
|
|
|
|
>,
|
|
|
|
|
|
|
|
resize: Box<
|
|
|
|
dyn FnMut(f32, f32, &TargetMode<Vec<Arc<Image>>>, &mut World) -> Result<()>
|
|
|
|
+ Send
|
|
|
|
+ Sync
|
|
|
|
+ 'static,
|
|
|
|
>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl SceneHandle {
|
|
|
|
fn new<T: TScene>(priority: u32) -> Self {
|
|
|
|
Self {
|
|
|
|
type_id: TypeId::of::<T>(),
|
|
|
|
priority,
|
|
|
|
render: Box::new(|recorder, images, indices, world| {
|
|
|
|
world
|
|
|
|
.resources
|
|
|
|
.get_mut_unchecked::<T>()
|
|
|
|
.process(recorder, images, indices, world)
|
|
|
|
}),
|
|
|
|
|
|
|
|
resize: Box::new(|width, height, images, world| {
|
|
|
|
world
|
|
|
|
.resources
|
|
|
|
.get_mut_unchecked::<T>()
|
2025-03-03 07:45:50 +00:00
|
|
|
.resize(width, height, images, world)
|
2025-03-01 05:01:46 +00:00
|
|
|
}),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
pub struct RenderBackend {
|
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>,
|
|
|
|
|
2025-03-01 05:01:46 +00:00
|
|
|
render_routines: Vec<SceneHandle>,
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
impl RenderBackend {
|
2025-02-26 13:51:44 +00:00
|
|
|
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,
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
render_routines: Vec::new(),
|
2024-08-23 11:22:09 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
pub(crate) fn required_image_usage() -> VkImageUsageFlagBits {
|
|
|
|
VK_IMAGE_USAGE_TRANSFER_DST_BIT.into()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
impl RenderBackend {
|
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"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
// make a call to the connected scenes
|
|
|
|
self.render_routines
|
|
|
|
.iter_mut()
|
2025-03-01 05:01:46 +00:00
|
|
|
.try_for_each(|scene_handle| {
|
|
|
|
(scene_handle.render)(
|
2025-02-28 15:41:59 +00:00
|
|
|
&mut buffer_recorder,
|
|
|
|
&*self.swapchain_images.lock().unwrap(),
|
|
|
|
&image_indices,
|
|
|
|
world,
|
2025-03-01 05:01:46 +00:00
|
|
|
)
|
2025-02-28 15:41:59 +00:00
|
|
|
})?;
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
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-28 15:41:59 +00:00
|
|
|
self.render_routines
|
|
|
|
.iter_mut()
|
2025-03-01 05:01:46 +00:00
|
|
|
.try_for_each(|scene_handle| {
|
|
|
|
(scene_handle.resize)(width as f32, height as f32, &images, world)
|
2025-02-28 15:41:59 +00:00
|
|
|
})?;
|
2024-08-23 11:22:09 +00:00
|
|
|
|
|
|
|
Ok(())
|
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
/// lower priority means it is more important
|
|
|
|
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
|
2025-03-01 05:01:46 +00:00
|
|
|
self.render_routines.push(SceneHandle::new::<T>(priority));
|
|
|
|
self.render_routines
|
|
|
|
.sort_by_key(|scene_handle| scene_handle.priority);
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
|
2025-02-28 15:41:59 +00:00
|
|
|
pub fn remove_render_routine<T: TScene>(&mut self) {
|
2025-03-01 05:01:46 +00:00
|
|
|
if let Some(index) = self
|
2025-02-28 15:41:59 +00:00
|
|
|
.render_routines
|
2024-08-23 11:22:09 +00:00
|
|
|
.iter()
|
2025-03-01 05:01:46 +00:00
|
|
|
.position(|scene_handle| scene_handle.type_id == TypeId::of::<T>())
|
2024-08-23 11:22:09 +00:00
|
|
|
{
|
2025-02-28 19:42:07 +00:00
|
|
|
self.render_routines.remove(index as usize);
|
2024-08-23 11:22:09 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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-28 15:41:59 +00:00
|
|
|
impl RenderBackend {
|
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);
|
|
|
|
}
|
|
|
|
}
|