diff options
| author | HampusM <hampus@hampusmat.com> | 2026-03-28 16:06:11 +0100 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-03-28 16:06:11 +0100 |
| commit | bb8fad66f4b839a5b0bbc8a81ac4a080dbe8575c (patch) | |
| tree | d17d22a04c22957060aeb89dd1766afdc89424cb /engine/src | |
| parent | 73d976ae7b98362613e700e48a834063be0f9d41 (diff) | |
feat(engine): make rendering pass-based
Diffstat (limited to 'engine/src')
| -rw-r--r-- | engine/src/renderer.rs | 128 | ||||
| -rw-r--r-- | engine/src/renderer/opengl.rs | 7 | ||||
| -rw-r--r-- | engine/src/shader.rs | 5 |
3 files changed, 116 insertions, 24 deletions
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<RenderPass>, +} + +#[derive(Debug)] +pub struct RenderPass +{ + pub renderer_ctx_ent_id: Uid, + pub surface_id: SurfaceId, + pub commands: Vec<Command>, +} + #[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<CtxUsedByWindow, Wildcard>], - )>, +pub fn add_main_render_passes( + renderer_ctx_query: Query< + (&ObjectStore, &[Pair<CtxUsedByWindow, Wildcard>]), + (With<CommandQueue>,), + >, renderable_query: Query<RenderableEntity<'_>, (Without<NoDraw>,)>, assets: Single<Assets>, shader_context: Single<ShaderContext>, + mut render_passes: Single<RenderPasses>, 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>(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<CtxUsedByWindow, Wildcard>])>, + mut render_passes: Single<RenderPasses>, + 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::<CommandQueue>() + 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::<SurfaceSpec>() else { + tracing::debug!( + window_entity_id=%window_ent_id, + "Window entity does not have a {} component", + type_name::<SurfaceSpec>() + ); + continue; + }; command_queue.push(Command::SwapBuffers(surface_spec.id)); } diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index 261148b..5ed2aaa 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -86,6 +86,7 @@ use crate::renderer::{ GraphicsProperties, PRE_RENDER_PHASE, RENDER_PHASE, + RenderPasses, SurfaceId, SurfaceSpec, WindowUsingRendererCtx, @@ -159,7 +160,11 @@ impl ecs::extension::Extension for Extension collector.add_declared_entity(&RENDER_PHASE); collector.add_declared_entity(&POST_RENDER_PHASE); - collector.add_system(*RENDER_PHASE, super::enqueue_commands); + let _ = collector.add_sole(RenderPasses::default()); + + collector.add_system(*PRE_RENDER_PHASE, super::add_main_render_passes); + + collector.add_system(*RENDER_PHASE, super::enqueue_commands_from_render_passes); collector.add_system(*RENDER_PHASE, handle_commands); collector.add_system(*POST_RENDER_PHASE, prepare_windows); diff --git a/engine/src/shader.rs b/engine/src/shader.rs index ae0be1d..2b16c47 100644 --- a/engine/src/shader.rs +++ b/engine/src/shader.rs @@ -8,7 +8,7 @@ use std::str::Utf8Error; use bitflags::{bitflags, bitflags_match}; use ecs::pair::{ChildOf, Pair}; -use ecs::phase::{Phase, START as START_PHASE}; +use ecs::phase::{POST_UPDATE as POST_UPDATE_PHASE, Phase, START as START_PHASE}; use ecs::sole::Single; use ecs::{Component, Sole, declare_entity}; use shader_slang::{ @@ -38,7 +38,6 @@ use crate::reflection::{ StructField as StructFieldReflection, With, }; -use crate::renderer::PRE_RENDER_PHASE; use crate::shader::default::{ ASSET_LABEL, enqueue_set_shader_bindings as default_shader_enqueue_set_shader_bindings, @@ -977,7 +976,7 @@ impl ecs::extension::Extension for Extension collector.add_system(*IMPORT_SHADERS_PHASE, load_modules); collector.add_system( - *PRE_RENDER_PHASE, + *POST_UPDATE_PHASE, default_shader_enqueue_set_shader_bindings, ); } |
