engine/presentation/src/renderbackend.rs

297 lines
8.2 KiB
Rust
Raw Normal View History

2024-08-23 11:22:09 +00:00
use crate::Result;
use crate::prelude::*;
2024-08-23 11:22:09 +00:00
use cgmath::{Matrix4, SquareMatrix};
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,
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 {
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);
}
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,
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);
}
}