engine_render: Add first render
Some checks failed
Build legacy Nix package on Ubuntu / build (push) Failing after 8m50s

This commit is contained in:
Florian RICHER 2025-05-24 18:04:56 +02:00
parent 15565d03c1
commit dbe415d262
Signed by: florian.richer
GPG key ID: C73D37CBED7BFC77
2 changed files with 129 additions and 0 deletions

View file

@ -11,6 +11,7 @@ use engine_vulkan::{
use engine_window::raw_handle::WindowWrapper; use engine_window::raw_handle::WindowWrapper;
use window::WindowRenderPlugin; use window::WindowRenderPlugin;
pub mod render;
pub mod window; pub mod window;
#[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)] #[derive(Debug, Hash, PartialEq, Eq, Clone, SystemSet)]
@ -65,6 +66,12 @@ impl Plugin for RenderPlugin {
let mut render_app = SubApp::new(); let mut render_app = SubApp::new();
render_app.update_schedule = Some(Render.intern()); render_app.update_schedule = Some(Render.intern());
render_app.add_schedule(Render::base_schedule()); render_app.add_schedule(Render::base_schedule());
render_app.add_systems(
Render,
render::render_system
.in_set(RenderSystems::Render)
.run_if(render::can_render),
);
extract_app_resources(app.world_mut(), render_app.world_mut()); extract_app_resources(app.world_mut(), render_app.world_mut());

View file

@ -0,0 +1,122 @@
use bevy_ecs::system::{Res, ResMut};
use engine_vulkan::{VulkanCommandBufferAllocator, VulkanDevice, VulkanGraphicsQueue};
use vulkano::{
Validated, VulkanError,
command_buffer::{
AutoCommandBufferBuilder, CommandBufferUsage, RenderingAttachmentInfo, RenderingInfo,
},
render_pass::{AttachmentLoadOp, AttachmentStoreOp},
swapchain::{SwapchainAcquireFuture, SwapchainPresentInfo, acquire_next_image},
sync::{self, GpuFuture},
};
use crate::window::{WindowSurface, WindowSurfaceData};
pub fn can_render(window_surface: Res<WindowSurface>) -> bool {
window_surface.surface.is_some()
}
pub fn render_system(
mut window_surface: ResMut<WindowSurface>,
command_buffer_allocator: Res<VulkanCommandBufferAllocator>,
graphics_queue: Res<VulkanGraphicsQueue>,
device: Res<VulkanDevice>,
) {
{
let surface = window_surface.surface.as_ref().unwrap();
if surface.viewport.extent[0] == 0.0 || surface.viewport.extent[1] == 0.0 {
return;
}
}
let (image_index, acquire_future) =
match acquire_image(&mut window_surface.surface.as_mut().unwrap()) {
Some(r) => r,
None => return,
};
let mut builder = AutoCommandBufferBuilder::primary(
command_buffer_allocator.0.clone(),
graphics_queue.0.queue_family_index(),
CommandBufferUsage::OneTimeSubmit,
)
.expect("failed to create command buffer builder");
{
let surface = window_surface.surface.as_ref().unwrap();
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, 0.0].into()),
..RenderingAttachmentInfo::image_view(
surface.attachment_image_views[image_index as usize].clone(),
)
})],
..Default::default()
})
.unwrap()
.set_viewport(0, [surface.viewport.clone()].into_iter().collect())
.unwrap();
}
builder.end_rendering().unwrap();
let command_buffer = builder.build().unwrap();
{
let surface = window_surface.surface.as_mut().unwrap();
let future = surface
.previous_frame_end
.take()
.unwrap()
.join(acquire_future)
.then_execute(graphics_queue.0.clone(), command_buffer)
.unwrap()
.then_swapchain_present(
graphics_queue.0.clone(),
SwapchainPresentInfo::swapchain_image_index(surface.swapchain.clone(), image_index),
)
.then_signal_fence_and_flush();
match future.map_err(Validated::unwrap) {
Ok(future) => {
surface.previous_frame_end = Some(future.boxed_send_sync());
}
Err(VulkanError::OutOfDate) => {
surface.recreate_swapchain = true;
surface.previous_frame_end = Some(sync::now(device.0.clone()).boxed_send_sync());
}
Err(e) => {
println!("failed to flush future: {e}");
surface.previous_frame_end = Some(sync::now(device.0.clone()).boxed_send_sync());
}
}
}
}
fn acquire_image(surface: &mut WindowSurfaceData) -> Option<(u32, SwapchainAcquireFuture)> {
surface
.previous_frame_end
.as_mut()
.unwrap()
.cleanup_finished();
let (image_index, suboptimal, acquire_future) =
match acquire_next_image(surface.swapchain.clone(), None).map_err(Validated::unwrap) {
Ok(r) => r,
Err(VulkanError::OutOfDate) => {
surface.recreate_swapchain = true;
return None;
}
Err(e) => panic!("failed to acquire next image: {e}"),
};
if suboptimal {
surface.recreate_swapchain = true;
}
Some((image_index, acquire_future))
}