From bb8fad66f4b839a5b0bbc8a81ac4a080dbe8575c Mon Sep 17 00:00:00 2001 From: HampusM Date: Sat, 28 Mar 2026 16:06:11 +0100 Subject: feat(engine): make rendering pass-based --- engine/src/renderer.rs | 128 +++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 108 insertions(+), 20 deletions(-) (limited to 'engine/src/renderer.rs') diff --git a/engine/src/renderer.rs b/engine/src/renderer.rs index 7865ac4..a04fd4f 100644 --- a/engine/src/renderer.rs +++ b/engine/src/renderer.rs @@ -4,11 +4,13 @@ use std::sync::atomic::{AtomicU64, Ordering}; use bitflags::bitflags; use ecs::actions::Actions; +use ecs::entity::obtainer::Obtainer as EntityObtainer; use ecs::pair::{ChildOf, Pair, Wildcard}; use ecs::phase::{POST_UPDATE as POST_UPDATE_PHASE, Phase}; -use ecs::query::term::Without; +use ecs::query::term::{With, Without}; use ecs::sole::Single; -use ecs::{Component, Query, declare_entity}; +use ecs::uid::Uid; +use ecs::{Component, Query, Sole, declare_entity}; use crate::asset::{Assets, Handle as AssetHandle}; use crate::builder; @@ -142,6 +144,20 @@ impl SurfaceId } } +#[derive(Debug, Default, Sole)] +pub struct RenderPasses +{ + pub passes: VecDeque, +} + +#[derive(Debug)] +pub struct RenderPass +{ + pub renderer_ctx_ent_id: Uid, + pub surface_id: SurfaceId, + pub commands: Vec, +} + #[derive(Debug)] #[non_exhaustive] pub enum Command @@ -211,15 +227,15 @@ type RenderableEntity<'a> = ( ); #[tracing::instrument(skip_all)] -pub fn enqueue_commands( - renderer_ctx_query: Query<( - &mut CommandQueue, - &ObjectStore, - &[Pair], - )>, +pub fn add_main_render_passes( + renderer_ctx_query: Query< + (&ObjectStore, &[Pair]), + (With,), + >, renderable_query: Query, (Without,)>, assets: Single, shader_context: Single, + mut render_passes: Single, mut actions: Actions, ) { @@ -230,7 +246,7 @@ pub fn enqueue_commands( return; }; - for (renderer_ctx_ent_id, (mut command_queue, object_store, used_by_windows)) in + for (renderer_ctx_ent_id, (object_store, used_by_windows)) in renderer_ctx_query.iter_with_euids() { for ctx_used_by_window in used_by_windows { @@ -269,7 +285,17 @@ pub fn enqueue_commands( continue; }; - command_queue.push(Command::MakeCurrent(surface_spec.id)); + render_passes.passes.push_front(RenderPass { + renderer_ctx_ent_id, + surface_id: surface_spec.id, + commands: Vec::with_capacity(30), + }); + + let render_pass = render_passes.passes.front_mut().expect("Not possible"); + + render_pass + .commands + .push(Command::MakeCurrent(surface_spec.id)); let default_texture_asset = assets .get_handle_to_loaded::(TEXTURE_WHITE_1X1_ASSET_LABEL.clone()) @@ -278,10 +304,12 @@ pub fn enqueue_commands( if !object_store .contains_with_id(&ObjectId::Asset(default_texture_asset.id())) { - command_queue.push(Command::CreateTexture(default_texture_asset)); + render_pass + .commands + .push(Command::CreateTexture(default_texture_asset)); } - command_queue.push(Command::ClearBuffers( + render_pass.commands.push(Command::ClearBuffers( BufferClearMask::COLOR | BufferClearMask::DEPTH, )); @@ -337,13 +365,14 @@ pub fn enqueue_commands( continue; }; - command_queue.push(Command::CreateShaderProgram( + render_pass.commands.push(Command::CreateShaderProgram( ObjectId::Asset(shader_asset.id()), shader_program.clone(), )); } - command_queue + render_pass + .commands .push(Command::ActivateShader(ObjectId::Asset(shader_asset.id()))); let Some(model_material) = assets.get(&model_material_asset) else { @@ -362,7 +391,9 @@ pub fn enqueue_commands( if !object_store .contains_with_id(&ObjectId::Asset(texture_asset.id())) { - command_queue.push(Command::CreateTexture(texture_asset.clone())); + render_pass + .commands + .push(Command::CreateTexture(texture_asset.clone())); } } @@ -370,7 +401,7 @@ pub fn enqueue_commands( for (shader_binding_loc, shader_binding_val) in pending_shader_bindings.bindings.drain(..) { - command_queue.push(Command::SetShaderBinding( + render_pass.commands.push(Command::SetShaderBinding( shader_binding_loc, shader_binding_val, )); @@ -380,28 +411,85 @@ pub fn enqueue_commands( if let Some(draw_flags) = draw_flags.as_deref() && draw_flags.polygon_mode_config != PolygonModeConfig::default() { - command_queue.push(Command::SetPolygonModeConfig( + render_pass.commands.push(Command::SetPolygonModeConfig( draw_flags.polygon_mode_config.clone(), )); } if !object_store.contains_with_id(&ObjectId::Asset(mesh_asset.id())) { - command_queue.push(Command::CreateMesh( + render_pass.commands.push(Command::CreateMesh( ObjectId::Asset(mesh_asset.id()), mesh.clone(), )); } - command_queue.push(Command::DrawMesh(ObjectId::Asset(mesh_asset.id()))); + render_pass + .commands + .push(Command::DrawMesh(ObjectId::Asset(mesh_asset.id()))); if let Some(draw_flags) = draw_flags.as_deref() && draw_flags.polygon_mode_config != PolygonModeConfig::default() { - command_queue.push(Command::SetPolygonModeConfig( + render_pass.commands.push(Command::SetPolygonModeConfig( PolygonModeConfig::default(), )); } } + } + } +} + +#[tracing::instrument(skip_all)] +pub fn enqueue_commands_from_render_passes( + renderer_ctx_query: Query<(&mut CommandQueue, &[Pair])>, + mut render_passes: Single, + entity_obtainer: EntityObtainer, +) +{ + for render_pass in render_passes.passes.drain(..) { + let Some(renderer_ctx_ent) = + entity_obtainer.get_entity(render_pass.renderer_ctx_ent_id) + else { + tracing::error!( + renderer_ctx_entity_id=%render_pass.renderer_ctx_ent_id, + "Renderer context entity does not exist" + ); + + continue; + }; + + let Some(mut renderer_ctx_command_queue) = + renderer_ctx_ent.get_mut::() + else { + tracing::error!( + renderer_ctx_entity_id=%render_pass.renderer_ctx_ent_id, + "Renderer context entity does not have a command queue component" + ); + continue; + }; + + renderer_ctx_command_queue + .queue + .extend(render_pass.commands); + } + + for (mut command_queue, used_by_windows) in &renderer_ctx_query { + for ctx_used_by_window in used_by_windows { + let window_ent_id = ctx_used_by_window.id().target_entity(); + + let Some(window_ent) = ctx_used_by_window.get_target_ent() else { + tracing::error!("Window entity does not exist"); + continue; + }; + + let Some(surface_spec) = window_ent.get::() else { + tracing::debug!( + window_entity_id=%window_ent_id, + "Window entity does not have a {} component", + type_name::() + ); + continue; + }; command_queue.push(Command::SwapBuffers(surface_spec.id)); } -- cgit v1.2.3-18-g5258