move pipeline loader in world

This commit is contained in:
Florian RICHER 2025-06-12 14:24:11 +02:00
parent 9c651c5e0a
commit 6ba61e040e
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
5 changed files with 70 additions and 99 deletions

View file

@ -113,10 +113,7 @@ impl ApplicationHandler<UserEvent> for App {
// Now use the created context to load the scene // Now use the created context to load the scene
let mut scene_manager = SceneManager::new(); let mut scene_manager = SceneManager::new();
{ scene_manager.set_new_scene(Box::new(MainScene::default()));
let context = app_context.borrow();
scene_manager.load_scene(Box::new(MainScene::default()), &context);
}
self.scene_manager.insert(window_id, scene_manager); self.scene_manager.insert(window_id, scene_manager);
} }
@ -240,10 +237,7 @@ impl ApplicationHandler<UserEvent> for App {
} }
UserEvent::ChangeScene(window_id, scene) => { UserEvent::ChangeScene(window_id, scene) => {
if let Some(scene_manager) = self.scene_manager.get_mut(&window_id) { if let Some(scene_manager) = self.scene_manager.get_mut(&window_id) {
if let Some(app_context) = self.app_contexts.get(&window_id) { scene_manager.set_new_scene(scene);
let context = app_context.borrow();
scene_manager.replace_current_scene(scene, &context);
}
} }
} }
UserEvent::ChangeResolution(window_id, width, height) => { UserEvent::ChangeResolution(window_id, width, height) => {

View file

@ -5,6 +5,7 @@ use std::{
sync::{Arc, RwLock}, sync::{Arc, RwLock},
}; };
use bevy_ecs::resource::Resource;
use vulkano::{device::Device, format::Format, pipeline::GraphicsPipeline}; use vulkano::{device::Device, format::Format, pipeline::GraphicsPipeline};
use super::{GraphicsPipelineLoadFn, LoadableGraphicsPipeline}; use super::{GraphicsPipelineLoadFn, LoadableGraphicsPipeline};
@ -15,6 +16,7 @@ pub enum PipelineState {
Loaded, Loaded,
} }
#[derive(Resource)]
pub struct PipelineLoader { pub struct PipelineLoader {
device: Arc<Device>, device: Arc<Device>,
swapchain_image_format: Format, swapchain_image_format: Format,

View file

@ -11,11 +11,7 @@ use vulkano::{
memory::allocator::StandardMemoryAllocator, memory::allocator::StandardMemoryAllocator,
}; };
use crate::core::render::primitives::vulkan_resource::{ use bevy_ecs::resource::Resource;
VulkanCommandBufferAllocator, VulkanDevice, VulkanGraphicsQueue, VulkanMemoryAllocator,
VulkanTransferQueue,
};
use bevy_ecs::{resource::Resource, world::World};
use super::Texture; use super::Texture;

View file

@ -1,33 +1,42 @@
use std::cell::RefCell;
use std::error::Error; use std::error::Error;
use std::rc::Rc;
use crate::core::app::DEPTH_IMAGE_ID;
use crate::core::app::context::WindowContext; use crate::core::app::context::WindowContext;
use crate::core::render::primitives::vulkan_resource::{ use crate::core::render::primitives::vulkan_resource::{
VulkanCommandBufferAllocator, VulkanComputeQueue, VulkanDescriptorSetAllocator, VulkanDevice, VulkanCommandBufferAllocator, VulkanComputeQueue, VulkanDescriptorSetAllocator, VulkanDevice,
VulkanGraphicsQueue, VulkanInstance, VulkanMemoryAllocator, VulkanTransferQueue, VulkanGraphicsQueue, VulkanInstance, VulkanMemoryAllocator, VulkanTransferQueue,
}; };
use crate::core::render::resources::pipeline::PipelineLoader;
use crate::core::render::resources::texture::TextureLoader; use crate::core::render::resources::texture::TextureLoader;
use crate::core::scene::AsScene;
use bevy_ecs::world::World; use bevy_ecs::world::World;
use super::{AsScene, Scene}; use super::Scene;
#[derive(Default)]
pub struct SceneManager { pub struct SceneManager {
scenes: Vec<Scene>, current_scene: Option<Scene>,
current_scene_index: Option<usize>, new_scene: Option<Box<dyn AsScene>>,
} }
impl SceneManager { impl SceneManager {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
scenes: Vec::new(), current_scene: None,
current_scene_index: None, new_scene: None,
} }
} }
fn create_world_with_resources(window_context: &WindowContext) -> World { fn create_world_with_resources(window_context: &mut WindowContext) -> World {
let mut world = World::new(); let mut world = World::new();
let depth_image_view = window_context.with_renderer_mut(|renderer| {
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
});
let swapchain_image_view =
window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let vulkan_context = window_context.vulkan_context(); let vulkan_context = window_context.vulkan_context();
let vulkano_context = vulkan_context.vulkano_context(); let vulkano_context = vulkan_context.vulkano_context();
@ -47,6 +56,12 @@ impl SceneManager {
TextureLoader::select_best_suitable_queue(vulkan_graphics_queue, vulkan_transfer_queue), TextureLoader::select_best_suitable_queue(vulkan_graphics_queue, vulkan_transfer_queue),
); );
let pipeline_loader = PipelineLoader::new(
vulkan_device.clone(),
swapchain_image_view.format(),
depth_image_view.format(),
);
world.insert_resource(VulkanInstance(vulkan_instance.clone())); world.insert_resource(VulkanInstance(vulkan_instance.clone()));
world.insert_resource(VulkanDevice(vulkan_device.clone())); world.insert_resource(VulkanDevice(vulkan_device.clone()));
world.insert_resource(VulkanGraphicsQueue(vulkan_graphics_queue.clone())); world.insert_resource(VulkanGraphicsQueue(vulkan_graphics_queue.clone()));
@ -60,59 +75,37 @@ impl SceneManager {
vulkan_descriptor_set_allocator.clone(), vulkan_descriptor_set_allocator.clone(),
)); ));
world.insert_resource(texture_loader); world.insert_resource(texture_loader);
world.insert_resource(pipeline_loader);
world world
} }
pub fn load_scene(&mut self, scene_impl: Box<dyn AsScene>, window_context: &WindowContext) { pub fn set_new_scene(&mut self, scene_impl: Box<dyn AsScene>) {
let world = Self::create_world_with_resources(window_context); self.new_scene = Some(scene_impl);
let scene = Scene::new(scene_impl, world);
self.scenes.push(scene);
self.current_scene_index = Some(self.scenes.len() - 1);
}
pub fn replace_current_scene(
&mut self,
scene_impl: Box<dyn AsScene>,
window_context: &WindowContext,
) {
if let Some(index) = self.current_scene_index {
if index < self.scenes.len() {
self.scenes[index].unload();
let world = Self::create_world_with_resources(window_context);
self.scenes[index] = Scene::new(scene_impl, world);
}
} else {
self.load_scene(scene_impl, window_context);
}
} }
pub fn current_scene(&self) -> Option<&Scene> { pub fn current_scene(&self) -> Option<&Scene> {
if let Some(index) = self.current_scene_index { self.current_scene.as_ref()
self.scenes.get(index)
} else {
None
}
} }
pub fn current_scene_mut(&mut self) -> Option<&mut Scene> { pub fn current_scene_mut(&mut self) -> Option<&mut Scene> {
if let Some(index) = self.current_scene_index { self.current_scene.as_mut()
self.scenes.get_mut(index)
} else {
None
}
} }
pub fn load_scene_if_not_loaded( pub fn load_scene_if_not_loaded(
&mut self, &mut self,
window_context: &mut WindowContext, window_context: &mut WindowContext,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
if let Some(scene) = self.current_scene_mut() { if let Some(new_scene) = self.new_scene.take() {
if !scene.loaded() { let world = Self::create_world_with_resources(window_context);
scene.load(window_context)?; let mut scene = Scene::new(new_scene, world);
scene.load(window_context)?;
if let Some(mut current_scene) = self.current_scene.take() {
current_scene.unload();
} }
} else {
tracing::warn!("No scene found in SceneManager!"); self.current_scene = Some(scene);
} }
Ok(()) Ok(())
} }

View file

@ -9,7 +9,7 @@ use crate::core::render::primitives::camera::Camera3D;
use crate::core::render::primitives::transform::Transform; use crate::core::render::primitives::transform::Transform;
use crate::core::render::primitives::velocity::Velocity; use crate::core::render::primitives::velocity::Velocity;
use crate::core::render::primitives::vulkan_resource::{ use crate::core::render::primitives::vulkan_resource::{
VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanDevice, VulkanGraphicsQueue, VulkanCommandBufferAllocator, VulkanDescriptorSetAllocator, VulkanGraphicsQueue,
VulkanMemoryAllocator, VulkanMemoryAllocator,
}; };
use crate::core::render::primitives::{AsDescriptorSet, AsRecordable}; use crate::core::render::primitives::{AsDescriptorSet, AsRecordable};
@ -42,7 +42,6 @@ pub struct Square;
pub struct Cube; pub struct Cube;
pub struct MainSceneState { pub struct MainSceneState {
pipeline_loader: PipelineLoader,
square: SquareMesh, square: SquareMesh,
obj: ObjMesh, obj: ObjMesh,
camera: Camera3D, camera: Camera3D,
@ -65,18 +64,7 @@ impl AsScene for MainScene {
world: &mut World, world: &mut World,
window_context: &mut WindowContext, window_context: &mut WindowContext,
) -> Result<(), Box<dyn std::error::Error>> { ) -> Result<(), Box<dyn std::error::Error>> {
let depth_image_view = window_context.with_renderer_mut(|renderer| { let mut pipeline_loader = world.resource_mut::<PipelineLoader>();
renderer.get_additional_image_view(DEPTH_IMAGE_ID).clone()
});
let swapchain_image_view =
window_context.with_renderer(|renderer| renderer.swapchain_image_view().clone());
let mut pipeline_loader = PipelineLoader::new(
VulkanDevice::get_from_world(world).clone(),
swapchain_image_view.format(),
depth_image_view.format(),
);
pipeline_loader.register::<SimplePipeline>()?; pipeline_loader.register::<SimplePipeline>()?;
pipeline_loader.load_pending_pipelines()?; pipeline_loader.load_pending_pipelines()?;
@ -138,7 +126,6 @@ impl AsScene for MainScene {
self.state = Some(MainSceneState { self.state = Some(MainSceneState {
square, square,
obj, obj,
pipeline_loader,
camera, camera,
speed: 50.0, speed: 50.0,
scheduler, scheduler,
@ -257,36 +244,35 @@ impl AsScene for MainScene {
)?; )?;
let texture_loader = world.resource::<TextureLoader>(); let texture_loader = world.resource::<TextureLoader>();
let pipeline_loader = world.resource::<PipelineLoader>();
state pipeline_loader.with_pipeline::<SimplePipeline, _>(|pipeline| {
.pipeline_loader SimplePipeline::record_commands(
.with_pipeline::<SimplePipeline, _>(|pipeline| { &mut builder,
SimplePipeline::record_commands( &VulkanDescriptorSetAllocator::get_from_world(world),
&mut builder, pipeline,
&VulkanDescriptorSetAllocator::get_from_world(world), &state.square,
pipeline, &square_transform_uniform,
&state.square, vec![
&square_transform_uniform, camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
vec![ texture_loader.get_texture("wooden-crate").unwrap().clone(),
camera_uniform.clone() as Arc<dyn AsDescriptorSet>, ],
texture_loader.get_texture("wooden-crate").unwrap().clone(), )?;
],
)?;
SimplePipeline::record_commands( SimplePipeline::record_commands(
&mut builder, &mut builder,
&VulkanDescriptorSetAllocator::get_from_world(world), &VulkanDescriptorSetAllocator::get_from_world(world),
pipeline, pipeline,
&state.obj, &state.obj,
&cube_transform_uniform, &cube_transform_uniform,
vec![ vec![
camera_uniform.clone() as Arc<dyn AsDescriptorSet>, camera_uniform.clone() as Arc<dyn AsDescriptorSet>,
texture_loader.get_texture("cube-diffuse").unwrap().clone(), texture_loader.get_texture("cube-diffuse").unwrap().clone(),
], ],
)?; )?;
Ok(()) Ok(())
})?; })?;
RenderPassManager::end_rendering(&mut builder)?; RenderPassManager::end_rendering(&mut builder)?;