app: Move render_pass into scene
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m8s

This commit is contained in:
Florian RICHER 2025-05-29 00:17:21 +02:00
parent 131811a539
commit f835941432
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
7 changed files with 250 additions and 267 deletions

View file

@ -1,22 +1,15 @@
use std::collections::HashMap;
use std::sync::Arc;
use super::render::render_context::RenderContext;
use super::render::vulkan_context::VulkanContext;
use super::scene::SceneContext;
use crate::core::input::InputManager;
use crate::core::scene::SceneManager;
use crate::core::timer::Timer;
use crate::game::main_scene::MainScene;
use egui_winit_vulkano::{Gui, GuiConfig, egui};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, RenderingAttachmentInfo, RenderingInfo,
};
use vulkano::pipeline::graphics::viewport::Viewport;
use vulkano::render_pass::{AttachmentLoadOp, AttachmentStoreOp};
use egui_winit_vulkano::{Gui, GuiConfig};
use vulkano::swapchain::PresentMode;
use vulkano::sync::GpuFuture;
use vulkano_util::context::VulkanoContext;
use vulkano_util::renderer::VulkanoWindowRenderer;
use vulkano_util::window::{VulkanoWindows, WindowDescriptor};
use winit::application::ApplicationHandler;
use winit::event::WindowEvent;
@ -27,28 +20,9 @@ pub struct App {
vulkan_context: Arc<VulkanContext>,
vulkano_windows: Arc<VulkanoWindows>,
gui: HashMap<WindowId, Gui>,
clear_color: [f32; 3],
input_manager: InputManager,
scene_manager: SceneManager,
timer: Timer,
}
impl From<(&VulkanContext, &VulkanoWindowRenderer)> for RenderContext {
fn from((vulkan_context, renderer): (&VulkanContext, &VulkanoWindowRenderer)) -> Self {
RenderContext::new(
vulkan_context.vulkano_context().instance().clone(),
vulkan_context.vulkano_context().device().clone(),
vulkan_context.vulkano_context().graphics_queue().clone(),
vulkan_context.vulkano_context().compute_queue().clone(),
vulkan_context.vulkano_context().transfer_queue().cloned(),
vulkan_context.vulkano_context().memory_allocator().clone(),
vulkan_context.command_buffer_allocator().clone(),
vulkan_context.descriptor_set_allocator().clone(),
renderer.resolution(),
renderer.aspect_ratio(),
renderer.swapchain_format(),
)
}
input_manager: Arc<InputManager>,
timer: Arc<Timer>,
}
impl App {
@ -57,10 +31,9 @@ impl App {
vulkan_context: Arc::new(VulkanContext::new(vulkano_context)),
vulkano_windows: Arc::new(VulkanoWindows::default()),
gui: HashMap::new(),
clear_color: [0.0, 0.0, 0.0],
input_manager,
input_manager: Arc::new(input_manager),
scene_manager: SceneManager::new(),
timer: Timer::new(),
timer: Arc::new(Timer::new()),
}
}
}
@ -109,7 +82,10 @@ impl ApplicationHandler for App {
_device_id: winit::event::DeviceId,
event: winit::event::DeviceEvent,
) {
self.input_manager.process_device_event(&event);
match Arc::get_mut(&mut self.input_manager) {
Some(input_manager) => input_manager.process_device_event(&event),
None => log::error!("Failed to get a mutable reference to the input manager"),
}
}
fn window_event(&mut self, event_loop: &ActiveEventLoop, id: WindowId, event: WindowEvent) {
@ -118,10 +94,12 @@ impl ApplicationHandler for App {
.get_renderer_mut(id)
.unwrap();
let gui = self.gui.get_mut(&id).unwrap();
let render_context = RenderContext::from((self.vulkan_context.as_ref(), &*renderer));
if !gui.update(&event) {
self.input_manager.process_window_event(&event);
match Arc::get_mut(&mut self.input_manager) {
Some(input_manager) => input_manager.process_window_event(&event),
None => log::error!("Failed to get a mutable reference to the input manager"),
}
}
match event {
@ -136,86 +114,40 @@ impl ApplicationHandler for App {
renderer.resize();
}
WindowEvent::RedrawRequested => {
self.input_manager.update();
self.timer.update();
self.scene_manager.load_scene_if_not_loaded(&render_context);
match Arc::get_mut(&mut self.input_manager) {
Some(input_manager) => input_manager.update(),
None => log::error!("Failed to get a mutable reference to the input manager"),
}
match Arc::get_mut(&mut self.timer) {
Some(timer) => timer.update(),
None => log::error!("Failed to get a mutable reference to the timer"),
}
let scene_context = SceneContext::from((
&*renderer,
&self.vulkan_context,
&self.input_manager,
&self.timer,
));
self.scene_manager.load_scene_if_not_loaded(&scene_context);
if let Some(scene) = self.scene_manager.current_scene_mut() {
scene.update(&render_context, &self.input_manager, &self.timer);
scene.update(&scene_context);
let acquire_future = renderer.acquire(None, |_| {}).unwrap();
let acquire_future = scene.render(
&renderer.swapchain_image_view(),
acquire_future,
&scene_context,
gui,
);
match acquire_future {
Ok(future) => renderer.present(future, true),
Err(e) => {
log::error!("Error rendering scene: {}", e);
}
}
}
let acquire_future = renderer.acquire(None, |_| {}).unwrap();
let mut builder = AutoCommandBufferBuilder::primary(
self.vulkan_context.command_buffer_allocator().clone(),
self.vulkan_context
.vulkano_context()
.graphics_queue()
.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
{
let viewport = Viewport {
offset: [0.0, 0.0],
extent: renderer.resolution(),
depth_range: 0.0..=1.0,
};
builder
.begin_rendering(RenderingInfo {
color_attachments: vec![Some(RenderingAttachmentInfo {
load_op: AttachmentLoadOp::Clear,
store_op: AttachmentStoreOp::Store,
clear_value: Some(self.clear_color.into()),
..RenderingAttachmentInfo::image_view(
renderer.swapchain_image_view().clone(),
)
})],
..Default::default()
})
.unwrap()
.set_viewport(0, [viewport].into_iter().collect())
.unwrap();
}
if let Some(scene) = self.scene_manager.current_scene() {
scene.render(&render_context, &mut builder);
}
builder.end_rendering().unwrap();
let command_buffer = builder.build().unwrap();
let render_future = acquire_future
.then_execute(
self.vulkan_context
.vulkano_context()
.graphics_queue()
.clone(),
command_buffer,
)
.unwrap();
gui.immediate_ui(|gui| {
let ctx = gui.context();
egui::Window::new("Informations")
.vscroll(true)
.show(&ctx, |ui| {
ui.label(format!("Resolution: {:?}", renderer.resolution()));
ui.color_edit_button_rgb(&mut self.clear_color);
ui.label(format!("{:#?}", self.input_manager));
ui.label(format!("Delta time: {:?}", self.timer.delta_time()));
});
});
let render_future =
gui.draw_on_image(render_future, renderer.swapchain_image_view());
renderer.present(render_future.boxed(), true);
}
_ => {}
}

View file

@ -1,4 +1,3 @@
pub mod primitives;
pub mod render_context;
pub mod texture;
pub mod vulkan_context;

View file

@ -1,98 +0,0 @@
use std::sync::Arc;
use vulkano::{
command_buffer::allocator::StandardCommandBufferAllocator,
descriptor_set::allocator::StandardDescriptorSetAllocator,
device::{Device, Queue},
format::Format,
instance::Instance,
memory::allocator::StandardMemoryAllocator,
};
pub struct RenderContext {
instance: Arc<Instance>,
device: Arc<Device>,
graphics_queue: Arc<Queue>,
compute_queue: Arc<Queue>,
transfer_queue: Option<Arc<Queue>>,
memory_allocator: Arc<StandardMemoryAllocator>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
window_size: [f32; 2],
aspect_ratio: f32,
swapchain_format: Format,
}
impl RenderContext {
pub fn new(
instance: Arc<Instance>,
device: Arc<Device>,
graphics_queue: Arc<Queue>,
compute_queue: Arc<Queue>,
transfer_queue: Option<Arc<Queue>>,
memory_allocator: Arc<StandardMemoryAllocator>,
command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
window_size: [f32; 2],
aspect_ratio: f32,
swapchain_format: Format,
) -> Self {
Self {
instance,
device,
graphics_queue,
compute_queue,
transfer_queue,
memory_allocator,
command_buffer_allocator,
descriptor_set_allocator,
window_size,
aspect_ratio,
swapchain_format,
}
}
pub fn instance(&self) -> &Arc<Instance> {
&self.instance
}
pub fn device(&self) -> &Arc<Device> {
&self.device
}
pub fn graphics_queue(&self) -> &Arc<Queue> {
&self.graphics_queue
}
pub fn compute_queue(&self) -> &Arc<Queue> {
&self.compute_queue
}
pub fn transfer_queue(&self) -> Option<&Arc<Queue>> {
self.transfer_queue.as_ref()
}
pub fn memory_allocator(&self) -> &Arc<StandardMemoryAllocator> {
&self.memory_allocator
}
pub fn command_buffer_allocator(&self) -> &Arc<StandardCommandBufferAllocator> {
&self.command_buffer_allocator
}
pub fn descriptor_set_allocator(&self) -> &Arc<StandardDescriptorSetAllocator> {
&self.descriptor_set_allocator
}
pub fn window_size(&self) -> &[f32; 2] {
&self.window_size
}
pub fn aspect_ratio(&self) -> f32 {
self.aspect_ratio
}
pub fn swapchain_format(&self) -> Format {
self.swapchain_format
}
}

82
src/core/scene/context.rs Normal file
View file

@ -0,0 +1,82 @@
use std::sync::Arc;
use vulkano::{
command_buffer::allocator::StandardCommandBufferAllocator,
descriptor_set::allocator::StandardDescriptorSetAllocator,
device::{Device, Queue},
format::Format,
instance::Instance,
memory::allocator::StandardMemoryAllocator,
};
use vulkano_util::renderer::VulkanoWindowRenderer;
use crate::core::{input::InputManager, render::vulkan_context::VulkanContext, timer::Timer};
pub struct SceneContext {
pub instance: Arc<Instance>,
pub device: Arc<Device>,
pub graphics_queue: Arc<Queue>,
pub compute_queue: Arc<Queue>,
pub transfer_queue: Option<Arc<Queue>>,
pub memory_allocator: Arc<StandardMemoryAllocator>,
pub command_buffer_allocator: Arc<StandardCommandBufferAllocator>,
pub descriptor_set_allocator: Arc<StandardDescriptorSetAllocator>,
pub window_size: [f32; 2],
pub aspect_ratio: f32,
pub swapchain_format: Format,
pub input_manager: Arc<InputManager>,
pub timer: Arc<Timer>,
}
impl
From<(
&VulkanoWindowRenderer,
&Arc<VulkanContext>,
&Arc<InputManager>,
&Arc<Timer>,
)> for SceneContext
{
fn from(
(renderer, vulkan_context, input_manager, timer): (
&VulkanoWindowRenderer,
&Arc<VulkanContext>,
&Arc<InputManager>,
&Arc<Timer>,
),
) -> Self {
let (command_buffer_allocator, descriptor_set_allocator) = {
(
vulkan_context.command_buffer_allocator().clone(),
vulkan_context.descriptor_set_allocator().clone(),
)
};
let (instance, device, graphics_queue, compute_queue, transfer_queue, memory_allocator) = {
let vulkan_context = vulkan_context.vulkano_context();
(
vulkan_context.instance().clone(),
vulkan_context.device().clone(),
vulkan_context.graphics_queue().clone(),
vulkan_context.compute_queue().clone(),
vulkan_context.transfer_queue().cloned(),
vulkan_context.memory_allocator().clone(),
)
};
Self {
instance,
device,
graphics_queue,
compute_queue,
transfer_queue,
memory_allocator,
command_buffer_allocator,
descriptor_set_allocator,
window_size: renderer.window_size(),
aspect_ratio: renderer.aspect_ratio(),
swapchain_format: renderer.swapchain_format(),
input_manager: input_manager.clone(),
timer: timer.clone(),
}
}
}

View file

@ -1,23 +1,4 @@
use vulkano::command_buffer::{AutoCommandBufferBuilder, PrimaryAutoCommandBuffer};
use super::{input::InputManager, render::render_context::RenderContext, timer::Timer};
pub trait Scene {
fn loaded(&self) -> bool;
fn load(&mut self, render_context: &RenderContext);
fn update(
&mut self,
render_context: &RenderContext,
input_manager: &InputManager,
timer: &Timer,
);
fn render(
&self,
render_context: &RenderContext,
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
);
fn unload(&mut self);
}
use super::{Scene, SceneContext};
pub struct SceneManager {
current_scene: Option<Box<dyn Scene>>,
@ -30,10 +11,10 @@ impl SceneManager {
}
}
pub fn load_scene_if_not_loaded(&mut self, render_context: &RenderContext) {
pub fn load_scene_if_not_loaded(&mut self, scene_context: &SceneContext) {
if let Some(current_scene) = self.current_scene.as_mut() {
if !current_scene.loaded() {
current_scene.load(render_context);
current_scene.load(scene_context);
}
}
}

24
src/core/scene/mod.rs Normal file
View file

@ -0,0 +1,24 @@
use std::{error::Error, sync::Arc};
use egui_winit_vulkano::Gui;
use vulkano::{image::view::ImageView, sync::GpuFuture};
mod context;
pub use context::SceneContext;
mod manager;
pub use manager::SceneManager;
pub trait Scene {
fn loaded(&self) -> bool;
fn load(&mut self, scene_context: &SceneContext);
fn update(&mut self, scene_context: &SceneContext);
fn render(
&mut self,
image_view: &Arc<ImageView>,
acquire_future: Box<dyn GpuFuture>,
scene_context: &SceneContext,
gui: &mut Gui,
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>>;
fn unload(&mut self);
}

View file

@ -1,13 +1,20 @@
use crate::core::input::InputManager;
use std::{error::Error, sync::Arc};
use crate::core::render::primitives::camera::Camera;
use crate::core::render::render_context::RenderContext;
use crate::core::render::texture::Texture;
use crate::core::scene::Scene;
use crate::core::timer::Timer;
use crate::core::scene::SceneContext;
use egui_winit_vulkano::{Gui, egui};
use glam::{Mat4, Vec3};
use vulkano::command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryAutoCommandBuffer,
PrimaryCommandBufferAbstract,
use vulkano::{
command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, PrimaryCommandBufferAbstract,
RenderingAttachmentInfo, RenderingInfo,
},
image::view::ImageView,
pipeline::graphics::viewport::Viewport,
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
sync::GpuFuture,
};
use super::assets::square::Square;
@ -29,11 +36,11 @@ impl Scene for MainScene {
self.state.is_some()
}
fn load(&mut self, render_context: &RenderContext) {
fn load(&mut self, scene_context: &SceneContext) {
let square = Square::new(
render_context.device(),
render_context.memory_allocator(),
render_context.swapchain_format(),
&scene_context.device,
&scene_context.memory_allocator,
scene_context.swapchain_format,
)
.unwrap();
@ -45,22 +52,22 @@ impl Scene for MainScene {
),
Mat4::perspective_rh_gl(
std::f32::consts::FRAC_PI_2,
render_context.aspect_ratio(),
scene_context.aspect_ratio,
0.01,
100.0,
),
);
let mut uploads = AutoCommandBufferBuilder::primary(
render_context.command_buffer_allocator().clone(),
render_context.graphics_queue().queue_family_index(),
scene_context.command_buffer_allocator.clone(),
scene_context.graphics_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.unwrap();
let texture = Texture::from_file(
render_context.device(),
render_context.memory_allocator(),
&scene_context.device,
&scene_context.memory_allocator,
&mut uploads,
"res/textures/wooden-crate.jpg",
)
@ -69,7 +76,7 @@ impl Scene for MainScene {
let _ = uploads
.build()
.unwrap()
.execute(render_context.graphics_queue().clone())
.execute(scene_context.graphics_queue.clone())
.unwrap();
self.state = Some(MainSceneState {
@ -80,43 +87,99 @@ impl Scene for MainScene {
});
}
fn update(
&mut self,
render_context: &RenderContext,
input_manager: &InputManager,
timer: &Timer,
) {
fn update(&mut self, scene_context: &SceneContext) {
let state = self.state.as_mut().unwrap();
state.camera.update(input_manager, timer, state.speed, 10.0);
state.camera.update(
&scene_context.input_manager,
&scene_context.timer,
state.speed,
10.0,
);
state.camera.set_projection(Mat4::perspective_rh_gl(
std::f32::consts::FRAC_PI_2,
render_context.aspect_ratio(),
scene_context.aspect_ratio,
0.01,
100.0,
));
}
fn render(
&self,
render_context: &RenderContext,
builder: &mut AutoCommandBufferBuilder<PrimaryAutoCommandBuffer>,
) {
&mut self,
image_view: &Arc<ImageView>,
acquire_future: Box<dyn GpuFuture>,
scene_context: &SceneContext,
gui: &mut Gui,
) -> Result<Box<dyn GpuFuture>, Box<dyn Error>> {
let state = self.state.as_ref().unwrap();
let mut builder = AutoCommandBufferBuilder::primary(
scene_context.command_buffer_allocator.clone(),
scene_context.graphics_queue.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)?;
{
let viewport = Viewport {
offset: [0.0, 0.0],
extent: scene_context.window_size,
depth_range: 0.0..=1.0,
};
builder
.begin_rendering(RenderingInfo {
color_attachments: vec![Some(RenderingAttachmentInfo {
load_op: AttachmentLoadOp::Clear,
store_op: AttachmentStoreOp::Store,
clear_value: Some([0.0, 0.0, 0.0, 1.0].into()),
..RenderingAttachmentInfo::image_view(image_view.clone())
})],
..Default::default()
})?
.set_viewport(0, [viewport].into_iter().collect())?;
}
let camera_uniform = state
.camera
.create_buffer(render_context.memory_allocator())
.unwrap();
.create_buffer(&scene_context.memory_allocator)?;
state
.square
.render(
builder,
render_context.descriptor_set_allocator(),
&mut builder,
&scene_context.descriptor_set_allocator,
&camera_uniform,
&state.texture,
)
.unwrap();
builder.end_rendering()?;
let command_buffer = builder.build()?;
let render_future =
acquire_future.then_execute(scene_context.graphics_queue.clone(), command_buffer)?;
gui.immediate_ui(|gui| {
let ctx = gui.context();
egui::Window::new("Informations")
.vscroll(true)
.show(&ctx, |ui| {
ui.label(format!("Resolution: {:?}", scene_context.window_size));
ui.label(format!("{:#?}", scene_context.input_manager));
ui.label(format!(
"Delta time: {:?}",
scene_context.timer.delta_time()
));
});
});
let render_future = gui.draw_on_image(render_future, image_view.clone());
Ok(render_future)
}
fn unload(&mut self) {}