Rework render system

This commit is contained in:
hodasemi 2025-04-10 20:09:20 +02:00
parent f4663d3d68
commit 5ee7edf31b
14 changed files with 351 additions and 292 deletions

View file

@ -58,18 +58,18 @@ impl Context {
&mut self.sound_handler
}
pub fn next_frame<'a, C, F>(&mut self, world: &mut World, mut f: F) -> Result<bool>
pub fn events<'a, F>(&mut self, world: &World, mut f: F) -> Result<bool>
where
C: ResourceTrait + Send + Sync + 'static,
F: FnMut(&mut World, &mut C, Event<'_>) -> Result<()> + Send + Sync + 'a,
F: FnMut(Event<'_>) -> Result<()> + Send + Sync + 'a,
{
let render_core = self.render_core.clone();
let consumer = world.resources.get_mut_unchecked::<C>();
let w = unsafe { remove_life_time_mut(world) };
match self.presentation.poll_events(
|event| f(w, consumer, event),
|w, h| render_core.write().unwrap().resize(world, w, h),
|event| f(event),
|w, h| {
render_core.write().unwrap().resize(world, w, h);
Ok(())
},
) {
Ok(res) => {
if !res {
@ -84,13 +84,28 @@ impl Context {
}
}
if !self.render_core_mut().next_frame(world)? {
return Ok(false);
}
Ok(true)
}
pub fn start_frame(&self, world: &World) -> Result<()> {
self.render_core_mut().begin_frame(world)
}
pub fn render<F>(&self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
self.render_core_mut().render(render)
}
pub fn end_frame(&self, world: &World) -> Result<()> {
self.render_core_mut().end_frame(world)
}
pub fn render_core(&self) -> impl Deref<Target = RenderCore> + '_ {
self.render_core.read().unwrap()
}

View file

@ -14,33 +14,6 @@ use crate::prelude::*;
use std::collections::HashMap;
use std::sync::Arc;
#[derive(Resource)]
pub struct GuiHandlerRenderer;
impl TScene for GuiHandlerRenderer {
fn process(
&mut self,
buffer_recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>,
world: &mut World,
) -> Result<()> {
let gui_handler: &mut GuiHandler = world.resources.get_mut()?;
gui_handler.process(buffer_recorder, indices)
}
fn resize(
&mut self,
window_width: f32,
window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World,
) -> Result<()> {
let gui_handler: &mut GuiHandler = world.resources.get_mut()?;
gui_handler.resize(window_width as u32, window_height as u32, images)
}
}
#[derive(Resource)]
pub struct Engine {
pub(crate) resource_base_path: String,
@ -173,11 +146,6 @@ impl Engine {
let asset_manager = AssetManager::new(&engine_settings)?;
let gui_handler = GuiHandler::new(create_info.gui_info, &context)?;
context
.render_core_mut()
.add_render_routine::<GuiHandlerRenderer>(10_000_000);
context.render_core_mut().add_render_routine::<Scene>(100);
world.resources.insert(context);
Scene::new(
@ -195,7 +163,6 @@ impl Engine {
direction_mapping.insert(Keycode::Down, GuiDirection::Down);
world.resources.insert(gui_handler);
world.resources.insert(GuiHandlerRenderer);
world.resources.insert(InputMap { direction_mapping });
world.resources.insert(asset_manager);
world.resources.insert(Engine {
@ -203,7 +170,12 @@ impl Engine {
});
world.resources.insert(engine_settings);
world.add_system(1_000_000, Self::main_system::<T>);
world.add_system(0, Self::event_system::<T>);
world.add_system(1, Self::start_frame);
world.add_system(u32::MAX, Self::end_frame);
world.add_system(100, Self::render_scene);
world.add_system(10_000_000, Self::render_gui);
Ok(())
}
@ -246,20 +218,63 @@ impl Engine {
}
impl Engine {
fn main_system<T: ResourceTrait + EventConsumer>(world: &mut World) -> Result<bool> {
let gui_handler = world.resources.get_mut_unchecked::<GuiHandler>();
let input_map = world.resources.get_unchecked::<InputMap>();
let context = world.resources.get_unchecked::<Context>();
fn event_system<T: ResourceTrait + EventConsumer>(
world: &World,
commands: &mut Commands,
consumer: &mut T,
gui_handler: &mut GuiHandler,
input_map: &mut InputMap,
context: &mut Context,
) -> Result<bool> {
let res = context.events(world, |event| {
Self::event(commands, gui_handler, input_map, consumer, event)
})?;
let res = world.resources.get_mut_unchecked::<Context>().next_frame(
world,
|world, consumer: &mut T, event| {
Self::event(world, context, gui_handler, input_map, consumer, event)
},
)?;
gui_handler.process_callbacks(world)?;
gui_handler.process_callbacks(commands)?;
Ok(res)
}
fn start_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result<bool> {
context.start_frame(world)?;
Ok(true)
}
fn end_frame(world: &World, _commands: &mut Commands, context: &mut Context) -> Result<bool> {
context.end_frame(world)?;
Ok(true)
}
fn render_scene(
world: &World,
_commands: &mut Commands,
context: &mut Context,
scene: &mut Scene,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| {
scene.process(recorder, images, indices, world)
},
)?;
Ok(true)
}
fn render_gui(
_commands: &mut Commands,
context: &mut Context,
gui_handler: &mut GuiHandler,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| { gui_handler.process(recorder, indices) },
)?;
Ok(true)
}
}

View file

@ -29,7 +29,7 @@ pub enum EngineEvent<'a> {
}
pub trait EventConsumer: Send + Sync + 'static {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()>;
fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()>;
}
#[derive(Resource)]
@ -39,8 +39,7 @@ pub struct InputMap {
impl Engine {
pub(crate) fn event<T: EventConsumer>(
world: &mut World,
context: &Context,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
input: &InputMap,
consumer: &mut T,
@ -49,68 +48,70 @@ impl Engine {
match event {
Event::MouseMotion(x, y) => {
gui_handler.set_mouse_pos(x, y)?;
consumer.event(world, EngineEvent::MouseMotion(x, y))?;
consumer.event(commands, EngineEvent::MouseMotion(x, y))?;
}
Event::MouseButtonDown(mouse_button) => {
if !gui_handler.mouse_down(mouse_button)? {
consumer.event(world, EngineEvent::MouseButtonDown(mouse_button))?;
consumer.event(commands, EngineEvent::MouseButtonDown(mouse_button))?;
}
}
Event::MouseButtonUp(mouse_button) => {
if !gui_handler.mouse_up(mouse_button)? {
consumer.event(world, EngineEvent::MouseButtonUp(mouse_button))?;
consumer.event(commands, EngineEvent::MouseButtonUp(mouse_button))?;
}
}
Event::MouseWheel(x, y, direction) => {
consumer.event(world, EngineEvent::MouseWheel(x, y, direction))?
consumer.event(commands, EngineEvent::MouseWheel(x, y, direction))?
}
Event::KeyDown(keycode) => {
Self::key_down_event(world, context, gui_handler, input, consumer, keycode)?;
Self::key_down_event(commands, gui_handler, input, consumer, keycode)?;
}
Event::KeyUp(keycode) => {
Self::key_up_event(world, gui_handler, input, consumer, keycode)?;
Self::key_up_event(commands, gui_handler, input, consumer, keycode)?;
}
Event::TextInput(text) => {
Self::text_input(gui_handler, text)?;
}
Event::ControllerButtonDown(controller, button) => {
Self::button_down_event(world, gui_handler, consumer, controller, button)?;
Self::button_down_event(commands, gui_handler, consumer, controller, button)?;
}
Event::ControllerButtonUp(controller, button) => {
Self::button_up_event(world, consumer, controller, button)?;
Self::button_up_event(commands, consumer, controller, button)?;
}
Event::ControllerAxis(controller) => {
if !gui_handler.check_navigatable() {
Self::axis_event(world, consumer, &controller)?
Self::axis_event(commands, consumer, &controller)?
} else {
gui_handler.update_selection(controller.direction())?;
}
}
Event::ControllerAdded(controller) => {
Self::controller_added(world, consumer, controller)?
Self::controller_added(commands, consumer, controller)?
}
Event::ControllerRemoved(controller) => {
Self::controller_removed(world, consumer, controller)?
Self::controller_removed(commands, consumer, controller)?
}
Event::JoystickAxis(joystick, axis_index, value) => consumer.event(
world,
commands,
EngineEvent::JoystickAxis(joystick, axis_index, value),
)?,
Event::JoystickButtonDown(joystick) => {
consumer.event(world, EngineEvent::JoystickButtonDown(joystick))?
consumer.event(commands, EngineEvent::JoystickButtonDown(joystick))?
}
Event::JoystickButtonUp(joystick) => {
consumer.event(world, EngineEvent::JoystickButtonUp(joystick))?
consumer.event(commands, EngineEvent::JoystickButtonUp(joystick))?
}
Event::JoystickAdded(joystick) => {
consumer.event(world, EngineEvent::JoystickAdded(joystick))?
consumer.event(commands, EngineEvent::JoystickAdded(joystick))?
}
Event::JoystickRemoved(joystick) => {
consumer.event(world, EngineEvent::JoystickRemoved(joystick))?
consumer.event(commands, EngineEvent::JoystickRemoved(joystick))?
}
Event::FileDrop(filename) => consumer.event(world, EngineEvent::FileDrop(filename))?,
Event::FileDrop(filename) => {
consumer.event(commands, EngineEvent::FileDrop(filename))?
}
}
Ok(())
@ -120,29 +121,29 @@ impl Engine {
impl Engine {
#[inline]
fn controller_added<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
consumer: &mut T,
controller: &Controller,
) -> Result<()> {
consumer.event(world, EngineEvent::ControllerAdded(controller))?;
consumer.event(commands, EngineEvent::ControllerAdded(controller))?;
Ok(())
}
#[inline]
fn controller_removed<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
consumer: &mut T,
controller: &Controller,
) -> Result<()> {
consumer.event(world, EngineEvent::ControllerRemoved(controller))?;
consumer.event(commands, EngineEvent::ControllerRemoved(controller))?;
Ok(())
}
#[inline]
fn key_up_event<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
input: &InputMap,
consumer: &mut T,
@ -154,15 +155,14 @@ impl Engine {
return Ok(());
}
consumer.event(world, EngineEvent::KeyUp(keycode))?;
consumer.event(commands, EngineEvent::KeyUp(keycode))?;
Ok(())
}
#[inline]
fn key_down_event<T: EventConsumer>(
world: &mut World,
context: &Context,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
input: &InputMap,
consumer: &mut T,
@ -186,50 +186,49 @@ impl Engine {
}
}
Keycode::Escape => {
if gui_handler.decline_topgui(world)? {
if gui_handler.decline_topgui(commands)? {
return Ok(());
}
}
Keycode::V => {
if let Some(writeable) = gui_handler.writeable() {
if let Some(content) = context.window_config().clipboard_content()? {
writeable.set_text(gui_handler, content)?;
}
}
}
_ => (),
}
consumer.event(world, EngineEvent::KeyDown(keycode))?;
consumer.event(commands, EngineEvent::KeyDown(keycode))?;
Ok(())
}
#[inline]
fn button_up_event<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
consumer: &mut T,
controller: &Controller,
button: ControllerButton,
) -> Result<()> {
consumer.event(world, EngineEvent::ControllerButtonUp(controller, button))?;
consumer.event(
commands,
EngineEvent::ControllerButtonUp(controller, button),
)?;
Ok(())
}
#[inline]
fn button_down_event<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
consumer: &mut T,
controller: &Controller,
button: ControllerButton,
) -> Result<()> {
if gui_handler.check_navigatable() {
Self::check_button_down(world, gui_handler, consumer, controller, button)?;
Self::check_button_down(commands, gui_handler, consumer, controller, button)?;
} else {
consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?;
consumer.event(
commands,
EngineEvent::ControllerButtonDown(controller, button),
)?;
}
Ok(())
@ -237,12 +236,12 @@ impl Engine {
#[inline]
fn axis_event<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
consumer: &mut T,
controller: &Controller,
) -> Result<()> {
consumer.event(
world,
commands,
EngineEvent::ControllerAxis(controller, controller.controller_axis()),
)?;
@ -251,7 +250,7 @@ impl Engine {
#[inline]
fn check_button_down<T: EventConsumer>(
world: &mut World,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
consumer: &mut T,
controller: &Controller,
@ -265,31 +264,31 @@ impl Engine {
}
ControllerButton::B => {
if gui_handler.decline_topgui(world)? {
if gui_handler.decline_topgui(commands)? {
return Ok(());
}
}
ControllerButton::RightButton => {
if gui_handler.next_tab_topgui(world, false)? {
if gui_handler.next_tab_topgui(commands, false)? {
return Ok(());
}
}
ControllerButton::LeftButton => {
if gui_handler.previous_tab_topgui(world, false)? {
if gui_handler.previous_tab_topgui(commands, false)? {
return Ok(());
}
}
ControllerButton::RightTrigger => {
if gui_handler.next_tab_topgui(world, true)? {
if gui_handler.next_tab_topgui(commands, true)? {
return Ok(());
}
}
ControllerButton::LeftTrigger => {
if gui_handler.previous_tab_topgui(world, true)? {
if gui_handler.previous_tab_topgui(commands, true)? {
return Ok(());
}
}
@ -333,8 +332,11 @@ impl Engine {
_ => (),
}
if !gui_handler.accept_custom_selection(world, button)? {
consumer.event(world, EngineEvent::ControllerButtonDown(controller, button))?;
if !gui_handler.accept_custom_selection(commands, button)? {
consumer.event(
commands,
EngineEvent::ControllerButtonDown(controller, button),
)?;
}
Ok(())

View file

@ -383,7 +383,7 @@ impl TScene for Scene {
buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>,
world: &mut World,
world: &World,
) -> anyhow::Result<()> {
self.frame_time = {
let now = world.now();
@ -484,7 +484,7 @@ impl TScene for Scene {
window_width: f32,
window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>,
_world: &mut World,
_world: &World,
) -> anyhow::Result<()> {
self.screen_width = window_width;
self.screen_height = window_height;

View file

@ -109,11 +109,14 @@ impl InputSettings {
pub struct Game;
impl Game {
pub fn update(&mut self, world: &mut World) -> Result<()> {
pub fn update(
&mut self,
commands: &mut Commands,
scene: &mut Scene,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
if FREE_CAMERA_CONTROL {
let now = world.now();
let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) =
world.resources.get_mut()?;
let now = commands.now();
camera_control.update(now, scene.view_mut())?;
}
@ -121,7 +124,7 @@ impl Game {
Ok(())
}
pub fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
pub fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
if let Some(event) = Self::motion_concepts(world, event)? {
match event {
EngineEvent::JoystickAdded(joystick) => {

View file

@ -14,12 +14,15 @@ pub enum GameState {
}
impl GameState {
pub fn update(world: &mut World) -> Result<bool> {
let me = world.resources.get_mut_unchecked::<Self>();
match me {
GameState::Startup => *me = GameState::Game(Game),
GameState::Game(game) => game.update(world)?,
pub fn update(
commands: &mut Commands,
game_state: &mut GameState,
scene: &mut Scene,
camera_control: &mut FreeCameraControl,
) -> Result<bool> {
match game_state {
GameState::Startup => *game_state = GameState::Game(Game),
GameState::Game(game) => game.update(commands, scene, camera_control)?,
}
Ok(true)
@ -27,10 +30,10 @@ impl GameState {
}
impl EventConsumer for GameState {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match self {
GameState::Startup => (),
GameState::Game(game) => game.event(world, event)?,
GameState::Game(game) => game.event(commands, event)?,
}
Ok(())

View file

@ -3,6 +3,13 @@ use anyhow::Result;
use ecs::*;
use engine::prelude::*;
struct CameraControlStart;
struct CameraControlEnd;
struct CameraControlMove {
x: u32,
y: u32,
}
fn main() -> Result<()> {
let mut world_builder = World::builder();
@ -11,6 +18,16 @@ fn main() -> Result<()> {
world_builder.add_system(10, GameState::update);
world_builder.resources.insert(GameState::default());
world_builder.events.register_event::<CameraControlStart>();
world_builder.events.register_event::<CameraControlEnd>();
world_builder.events.register_event::<CameraControlMove>();
world_builder.events.add_reader(Game::enable_camera_control);
world_builder
.events
.add_reader(Game::disable_camera_control);
world_builder.events.add_reader(Game::update_mouse);
let scene: &mut Scene = world_builder.resources.get_mut()?;
let view = scene.view_mut();
let camera_control = FreeCameraControl::new(view)?;
@ -28,12 +45,10 @@ enum GameState {
}
impl GameState {
fn update(world: &mut World) -> Result<bool> {
let me = world.resources.get_mut_unchecked::<Self>();
match me {
GameState::Startup => *me = GameState::Game(Game),
GameState::Game(game) => game.update(world)?,
fn update(commands: &mut Commands, game_state: &mut GameState) -> Result<bool> {
match game_state {
GameState::Startup => *game_state = GameState::Game(Game),
GameState::Game(game) => game.update(commands)?,
}
Ok(true)
@ -41,10 +56,10 @@ impl GameState {
}
impl EventConsumer for GameState {
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match self {
GameState::Startup => (),
GameState::Game(game) => game.event(world, event)?,
GameState::Game(game) => game.event(commands, event)?,
}
Ok(())
@ -54,26 +69,48 @@ impl EventConsumer for GameState {
struct Game;
impl Game {
fn update(&mut self, _world: &mut World) -> Result<()> {
fn enable_camera_control(
_: &CameraControlStart,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
camera_control.mouse_down();
Ok(())
}
fn event(&mut self, world: &mut World, event: EngineEvent<'_>) -> Result<()> {
fn disable_camera_control(
_: &CameraControlEnd,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
) -> Result<()> {
camera_control.mouse_release();
Ok(())
}
fn update_mouse(
camera_move: &CameraControlMove,
_commands: &mut Commands,
camera_control: &mut FreeCameraControl,
scene: &mut Scene,
) -> Result<()> {
camera_control.mouse_move(camera_move.x, camera_move.y, scene.view_mut())?;
Ok(())
}
fn update(&mut self, _commands: &mut Commands) -> Result<()> {
Ok(())
}
fn event(&mut self, commands: &mut Commands, event: EngineEvent<'_>) -> Result<()> {
match event {
EngineEvent::MouseButtonDown(MouseButton::Left) => {
let camera_control: &mut FreeCameraControl = world.resources.get_mut()?;
camera_control.mouse_down();
}
EngineEvent::MouseButtonUp(MouseButton::Left) => {
let camera_control: &mut FreeCameraControl = world.resources.get_mut()?;
camera_control.mouse_release();
}
EngineEvent::MouseMotion(x, y) => {
let (scene, camera_control): (&mut Scene, &mut FreeCameraControl) =
world.resources.get_mut()?;
camera_control.mouse_move(x, y, scene.view_mut())?;
commands.write_event(CameraControlStart)
}
EngineEvent::MouseButtonUp(MouseButton::Left) => commands.write_event(CameraControlEnd),
EngineEvent::MouseMotion(x, y) => commands.write_event(CameraControlMove { x, y }),
_ => (),
}

View file

@ -1,5 +1,5 @@
use context::prelude::*;
use ecs::World;
use ecs::Commands;
use std::{
sync::{
@ -26,13 +26,18 @@ where
T: Send + Sync + 'static,
G: TopLevelGui + TopGui + Send + Sync + 'static,
{
pub fn load<R, L>(world: &mut World, gui: Arc<G>, loader: L) -> Result<Self>
pub fn load<R, L>(
commands: &mut Commands,
gui_handler: &mut GuiHandler,
gui: Arc<G>,
loader: L,
) -> Result<Self>
where
R: Fn(T) -> Result<()> + Send + Sync + 'static,
T: Send + Sync + 'static,
L: FnOnce() -> T + Send + Sync + 'static,
{
gui.enable(world)?;
gui.enable(commands, gui_handler)?;
let (sender, receiver) = channel();
@ -61,8 +66,12 @@ where
}
}
pub fn take_result(mut self, world: &mut World) -> Result<T> {
self.gui.disable(world)?;
pub fn take_result(
mut self,
commands: &mut Commands,
gui_handler: &mut GuiHandler,
) -> Result<T> {
self.gui.disable(commands, gui_handler)?;
self.result
.take()
.ok_or(anyhow!("missing loading screen payload!"))

View file

@ -1,12 +1,10 @@
use crate::Result;
use crate::prelude::*;
use cgmath::{Matrix4, SquareMatrix};
use ecs::World;
use ui::prelude::*;
use vulkan_rs::prelude::*;
use std::any::TypeId;
use std::ops::Deref;
use std::sync::{
Arc, Mutex, RwLock,
@ -49,52 +47,6 @@ impl Default for VRTransformations {
}
}
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>()
.resize(width, height, images, world)
}),
}
}
}
pub struct RenderBackend {
device: Arc<Device>,
queue: Arc<Mutex<Queue>>,
@ -106,10 +58,12 @@ pub struct RenderBackend {
clear_color: RwLock<VkClearColorValue>,
command_buffer: Arc<CommandBuffer>,
render_routines: Vec<SceneHandle>,
buffer_recorder: Option<CommandBufferRecorder<'static>>,
}
unsafe impl Send for RenderBackend {}
unsafe impl Sync for RenderBackend {}
impl RenderBackend {
pub fn new(
device: &Arc<Device>,
@ -137,8 +91,7 @@ impl RenderBackend {
clear_color: RwLock::new(VkClearColorValue::float32([0.0, 0.0, 0.0, 1.0])),
command_buffer,
render_routines: Vec::new(),
buffer_recorder: None,
})
}
@ -160,11 +113,7 @@ impl RenderBackend {
*self.clear_color.write().unwrap() = VkClearColorValue::float32(clear_color);
}
pub fn render(
&mut self,
world: &mut World,
image_indices: TargetMode<usize>,
) -> Result<&Arc<CommandBuffer>> {
pub fn begin_frame(&mut self, image_indices: TargetMode<usize>) -> Result<()> {
// begin main command buffer
let mut buffer_recorder = self.command_buffer.begin(VkCommandBufferBeginInfo::new(
VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT,
@ -212,27 +161,39 @@ impl RenderBackend {
}
}
// make a call to the connected scenes
self.render_routines
.iter_mut()
.try_for_each(|scene_handle| {
(scene_handle.render)(
&mut buffer_recorder,
&*self.swapchain_images.lock().unwrap(),
&image_indices,
world,
)
})?;
self.buffer_recorder = Some(unsafe { std::mem::transmute(buffer_recorder) });
Ok(&self.command_buffer)
Ok(())
}
pub fn render<F>(&mut self, image_indices: TargetMode<usize>, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
render(
self.buffer_recorder.as_mut().unwrap(),
&*self.swapchain_images.lock().unwrap(),
&image_indices,
)?;
Ok(())
}
pub fn end_frame(&mut self) -> &Arc<CommandBuffer> {
self.buffer_recorder = None;
&self.command_buffer
}
pub fn resize(
&mut self,
world: &mut World,
_world: &World,
images: TargetMode<Vec<Arc<Image>>>,
width: u32,
height: u32,
_width: u32,
_height: u32,
) -> Result<()> {
self.image_count.store(
match &images {
@ -245,32 +206,16 @@ impl RenderBackend {
SeqCst,
);
self.render_routines
.iter_mut()
.try_for_each(|scene_handle| {
(scene_handle.resize)(width as f32, height as f32, &images, world)
})?;
// TODO
// self.render_routines
// .iter_mut()
// .try_for_each(|scene_handle| {
// (scene_handle.resize)(width as f32, height as f32, &images, world)
// })?;
Ok(())
}
/// lower priority means it is more important
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
self.render_routines.push(SceneHandle::new::<T>(priority));
self.render_routines
.sort_by_key(|scene_handle| scene_handle.priority);
}
pub fn remove_render_routine<T: TScene>(&mut self) {
if let Some(index) = self
.render_routines
.iter()
.position(|scene_handle| scene_handle.type_id == TypeId::of::<T>())
{
self.render_routines.remove(index as usize);
}
}
// getter
pub fn image_count(&self) -> usize {
self.image_count.load(SeqCst)

View file

@ -17,7 +17,7 @@ pub trait TScene: Resource + Send + Sync + 'static {
buffer_recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>,
world: &mut World,
world: &World,
) -> Result<()>;
fn resize(
@ -25,7 +25,7 @@ pub trait TScene: Resource + Send + Sync + 'static {
window_width: f32,
window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World,
world: &World,
) -> Result<()>;
}
@ -37,15 +37,35 @@ pub enum RenderCore {
}
impl RenderCore {
pub fn next_frame(&mut self, world: &mut World) -> Result<bool> {
pub fn begin_frame(&mut self, world: &World) -> Result<()> {
match self {
RenderCore::Wsi(rc) => rc.next_frame(world),
RenderCore::OpenVR(rc) => rc.next_frame(world),
RenderCore::OpenXR(rc) => rc.next_frame(world),
RenderCore::Wsi(rc) => rc.start_frame(world),
_ => todo!(),
}
}
pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> {
pub fn render<F>(&mut self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
match self {
RenderCore::Wsi(rc) => rc.render(render),
_ => todo!(),
}
}
pub fn end_frame(&mut self, world: &World) -> Result<()> {
match self {
RenderCore::Wsi(rc) => rc.end_frame(world),
_ => todo!(),
}
}
pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> {
match self {
RenderCore::Wsi(rc) => rc.resize(world, w, h),
RenderCore::OpenVR(rc) => rc.resize(world, w, h),
@ -65,23 +85,6 @@ impl RenderCore {
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR
}
/// lower priority means it is more important
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
match self {
RenderCore::Wsi(rc) => rc.add_render_routine::<T>(priority),
RenderCore::OpenVR(rc) => rc.add_render_routine::<T>(priority),
RenderCore::OpenXR(rc) => rc.add_render_routine::<T>(priority),
}
}
pub fn remove_render_routine<T: TScene>(&mut self) {
match self {
RenderCore::Wsi(rc) => rc.remove_render_routine::<T>(),
RenderCore::OpenVR(rc) => rc.remove_render_routine::<T>(),
RenderCore::OpenXR(rc) => rc.remove_render_routine::<T>(),
}
}
pub fn set_clear_color(&self, color: [f32; 4]) {
match self {
RenderCore::Wsi(rc) => rc.set_clear_color(color),

View file

@ -79,11 +79,11 @@ pub mod openvrrendercore {
unimplemented!()
}
pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> {
pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> {
unimplemented!()
}
pub fn next_frame(&mut self, _: &mut World) -> Result<bool> {
pub fn next_frame(&mut self, _: &World) -> Result<bool> {
unimplemented!()
}

View file

@ -103,7 +103,7 @@ impl VulkanWindowRenderCore {
Ok((window_render_core, TargetMode::Mono(())))
}
fn aquire_next_image_index(&mut self, world: &mut World) -> Result<()> {
fn aquire_next_image_index(&mut self, world: &World) -> Result<()> {
// there was a bug that a windows never reacted after it was minimized
// with this timeout, the window has 250ms delay
#[cfg(target_os = "windows")]
@ -145,7 +145,7 @@ impl VulkanWindowRenderCore {
self.format
}
pub fn resize(&mut self, world: &mut World, w: u32, h: u32) -> Result<()> {
pub fn resize(&mut self, world: &World, w: u32, h: u32) -> Result<()> {
self.swapchain.recreate((w, h))?;
let swapchain_images = self.swapchain.wrap_images(
@ -164,14 +164,33 @@ impl VulkanWindowRenderCore {
Ok(())
}
pub fn next_frame(&mut self, world: &mut World) -> Result<bool> {
pub fn start_frame(&mut self, world: &World) -> Result<()> {
self.aquire_next_image_index(world)?;
self.render_backend
.begin_frame(TargetMode::Mono(self.current_image_index.load(SeqCst)))?;
let command_buffer = self.render_backend.render(
world,
Ok(())
}
pub fn render<F>(&mut self, render: F) -> Result<()>
where
F: FnOnce(
&mut CommandBufferRecorder<'_>,
&TargetMode<Vec<Arc<Image>>>,
&TargetMode<usize>,
) -> Result<()>,
{
self.render_backend.render(
TargetMode::Mono(self.current_image_index.load(SeqCst)),
render,
)?;
Ok(())
}
pub fn end_frame(&mut self, world: &World) -> Result<()> {
let command_buffer = self.render_backend.end_frame();
let submits = &[SubmitInfo::default()
.add_wait_semaphore(
&*self.image_available_sem.read().unwrap(),
@ -194,7 +213,7 @@ impl VulkanWindowRenderCore {
let (w, h) = self.wsi.window_size();
self.resize(world, w, h)?;
self.render_fence.reset();
return Ok(true);
return Ok(());
}
// make sure command_buffer is ready
@ -205,22 +224,13 @@ impl VulkanWindowRenderCore {
)?;
self.render_fence.reset();
Ok(true)
Ok(())
}
pub fn set_clear_color(&self, color: [f32; 4]) {
self.render_backend.set_clear_color(color);
}
// post process handling
pub fn add_render_routine<T: TScene>(&mut self, priority: u32) {
self.render_backend.add_render_routine::<T>(priority);
}
pub fn remove_render_routine<T: TScene>(&mut self) {
self.render_backend.remove_render_routine::<T>();
}
// getter
pub fn image_count(&self) -> usize {
self.render_backend.image_count()

View file

@ -77,11 +77,11 @@ pub mod openxrrendercore {
unimplemented!()
}
pub fn resize(&mut self, _: &mut World, _: u32, _: u32) -> Result<()> {
pub fn resize(&mut self, _: &World, _: u32, _: u32) -> Result<()> {
unimplemented!()
}
pub fn next_frame(&mut self, _: &mut World) -> Result<bool> {
pub fn next_frame(&mut self, _: &World) -> Result<bool> {
unimplemented!()
}

View file

@ -55,7 +55,6 @@ impl SkyBox {
.sample_count;
let context = world.resources.get_mut_unchecked::<Context>();
context.render_core_mut().add_render_routine::<Self>(10);
let images = images.into();
let cube_map = Image::cube_map([
@ -166,6 +165,7 @@ impl SkyBox {
descriptor_set,
};
world.resources.insert(me);
world.add_system(10, Self::render_sky_box);
Ok(())
}
@ -178,6 +178,23 @@ impl SkyBox {
self.enabled = false;
}
fn render_sky_box(
world: &World,
_commands: &mut Commands,
context: &mut Context,
sky_box: &mut SkyBox,
) -> Result<bool> {
context.render(
|recorder: &mut CommandBufferRecorder<'_>,
images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>| {
sky_box.process(recorder, images, indices, world)
},
)?;
Ok(true)
}
fn create_render_target(
context: &Context,
images: &TargetMode<Vec<Arc<Image>>>,
@ -258,7 +275,7 @@ impl TScene for SkyBox {
buffer_recorder: &mut CommandBufferRecorder<'_>,
_images: &TargetMode<Vec<Arc<Image>>>,
indices: &TargetMode<usize>,
_world: &mut World,
_world: &World,
) -> Result<()> {
if !self.enabled {
return Ok(());
@ -290,7 +307,7 @@ impl TScene for SkyBox {
_window_width: f32,
_window_height: f32,
images: &TargetMode<Vec<Arc<Image>>>,
world: &mut World,
world: &World,
) -> Result<()> {
let sample_count = world
.resources