diff options
| author | HampusM <hampus@hampusmat.com> | 2026-03-21 17:54:55 +0100 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-03-21 17:54:55 +0100 |
| commit | 4f06675fa051e4b2f54960f76b75060c27ea8b7d (patch) | |
| tree | c1c4597146e90ee34f6cef20586d59d6e03be451 | |
| parent | d9bc1cc503c9a579dab263ed358a066053dbb495 (diff) | |
refactor(engine): add dedicated mesh creation renderer command
| -rw-r--r-- | engine/src/renderer.rs | 21 | ||||
| -rw-r--r-- | engine/src/renderer/object.rs | 10 | ||||
| -rw-r--r-- | engine/src/renderer/opengl.rs | 156 |
3 files changed, 130 insertions, 57 deletions
diff --git a/engine/src/renderer.rs b/engine/src/renderer.rs index 6c20102..8b37989 100644 --- a/engine/src/renderer.rs +++ b/engine/src/renderer.rs @@ -12,7 +12,7 @@ use ecs::query::term::Without; use ecs::sole::Single; use ecs::{Component, Query, declare_entity}; -use crate::asset::{Assets, Handle as AssetHandle, Label as AssetLabel}; +use crate::asset::{Assets, Label as AssetLabel}; use crate::builder; use crate::color::Color; use crate::data_types::dimens::Dimens; @@ -164,10 +164,8 @@ pub enum Command ActivateShader(ObjectId), SetShaderBinding(ShaderBindingLocation, ShaderBindingValue), CreateTexture(Texture), - DrawMesh - { - mesh_asset: AssetHandle<Mesh>, - }, + CreateMesh(ObjectId, Mesh), + DrawMesh(ObjectId), SetPolygonModeConfig(PolygonModeConfig), } @@ -332,6 +330,10 @@ pub fn enqueue_commands( continue; }; + let Some(mesh) = assets.get(mesh_asset) else { + continue; + }; + debug_assert!(model_spec.material_names.len() <= 1); let model_material_asset = match model_spec.find_first_material(&assets) { @@ -405,7 +407,14 @@ pub fn enqueue_commands( )); } - command_queue.push(Command::DrawMesh { mesh_asset: mesh_asset.clone() }); + if !object_store.contains_with_id(&ObjectId::Asset(mesh_asset.id())) { + command_queue.push(Command::CreateMesh( + ObjectId::Asset(mesh_asset.id()), + mesh.clone(), + )); + } + + command_queue.push(Command::DrawMesh(ObjectId::Asset(mesh_asset.id()))); if let Some(draw_flags) = draw_flags.as_deref() && draw_flags.polygon_mode_config != PolygonModeConfig::default() diff --git a/engine/src/renderer/object.rs b/engine/src/renderer/object.rs index 357bd6a..eba5bdf 100644 --- a/engine/src/renderer/object.rs +++ b/engine/src/renderer/object.rs @@ -5,12 +5,13 @@ use ecs::Component; use crate::asset::Id as AssetId; +pub type RawValue = u32; + /// Renderer object ID. #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] pub enum Id { Asset(AssetId), - Other(u64), } /// Renderer object store. @@ -91,18 +92,18 @@ impl<'store> StoreEntry<'store> #[derive(Debug, Clone)] pub struct Object { - raw: u32, + raw: RawValue, kind: Kind, } impl Object { - pub fn from_raw(raw: u32, kind: Kind) -> Self + pub fn from_raw(raw: RawValue, kind: Kind) -> Self { Self { raw, kind } } - pub fn as_raw(&self) -> u32 + pub fn as_raw(&self) -> RawValue { self.raw } @@ -120,4 +121,5 @@ pub enum Kind { Texture, ShaderProgram, + ImplementationSpecific, } diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs index c72a344..d31835a 100644 --- a/engine/src/renderer/opengl.rs +++ b/engine/src/renderer/opengl.rs @@ -69,6 +69,7 @@ use crate::renderer::object::{ Id as RendererObjectId, Kind as RendererObjectKind, Object as RendererObject, + RawValue as RendererObjectRawValue, Store as RendererObjectStore, }; use crate::renderer::opengl::glutin_compat::{ @@ -127,15 +128,16 @@ struct WindowGlConfig struct GraphicsContext { gl_context: ContextWithFns, - graphics_mesh_store: GraphicsMeshStore, surfaces: HashMap<SurfaceId, GlutinSurface<GlutinWindowSurface>>, uniform_buffer_objs: HashMap<u32, opengl_bindings::buffer::Buffer<u8>>, + objects: HashMap<RendererObjectRawValue, GraphicsContextObject>, + next_object_key: RendererObjectRawValue, } -#[derive(Debug, Default)] -struct GraphicsMeshStore +#[derive(Debug)] +enum GraphicsContextObject { - graphics_meshes: HashMap<AssetId, GraphicsMesh>, + Mesh(GraphicsMesh), } #[derive(Debug, Default)] @@ -170,6 +172,7 @@ fn handle_model_removed( observe: Observe<Pair<Removed, Model>>, renderer_ctx_query: Query<( &mut GraphicsContext, + &RendererObjectStore, Pair<RendererCtxUsedByWindow, Wildcard>, )>, assets: Single<Assets>, @@ -178,13 +181,15 @@ fn handle_model_removed( for evt_match in &observe { let model_ent_id = evt_match.id(); - for (renderer_ctx_ent_id, (mut graphics_ctx, renderer_ctx_used_by_window)) in - renderer_ctx_query.iter_with_euids() + for ( + renderer_ctx_ent_id, + (mut graphics_ctx, renderer_object_store, renderer_ctx_used_by_window), + ) in renderer_ctx_query.iter_with_euids() { let GraphicsContext { ref gl_context, - ref mut graphics_mesh_store, ref surfaces, + objects: ref mut graphics_ctx_objects, .. } = *graphics_ctx; @@ -198,10 +203,14 @@ fn handle_model_removed( continue; }; - if !graphics_mesh_store - .graphics_meshes - .contains_key(&mesh_asset.id()) - { + let Some(graphics_ctx_object_id) = renderer_object_store + .get_obj(&RendererObjectId::Asset(mesh_asset.id())) + .map(|obj| obj.as_raw()) + else { + continue; + }; + + if !graphics_ctx_objects.contains_key(&graphics_ctx_object_id) { continue; } @@ -245,16 +254,27 @@ fn handle_model_removed( "Cleaning up after model in renderer context" ); - let Some(mut graphics_mesh) = - graphics_mesh_store.graphics_meshes.remove(&mesh_asset.id()) + let Some(removed_graphics_ctx_obj) = + graphics_ctx_objects.remove(&graphics_ctx_object_id) else { tracing::warn!( model_entity_id=%model_ent_id, - "No mesh exists for model" + "No graphics context object exists for model" ); continue; }; + #[allow(irrefutable_let_patterns)] + let GraphicsContextObject::Mesh(mut graphics_mesh) = removed_graphics_ctx_obj + else { + tracing::error!( + model_entity_id=%model_ent_id, + "Graphics context object for model is not a mesh" + ); + + continue; + }; + graphics_mesh.destroy(&curr_gl_ctx); } } @@ -611,9 +631,10 @@ fn init_window_graphics( let renderer_ctx_ent_id = actions.spawn(( GraphicsContext { gl_context, - graphics_mesh_store: GraphicsMeshStore::default(), surfaces: HashMap::from([(surface_id, surface)]), uniform_buffer_objs: HashMap::new(), + objects: HashMap::new(), + next_object_key: RendererObjectRawValue::default(), }, RendererObjectStore::default(), RendererCommandQueue::default(), @@ -651,9 +672,10 @@ fn handle_commands( { let GraphicsContext { ref gl_context, - ref mut graphics_mesh_store, ref surfaces, ref mut uniform_buffer_objs, + objects: ref mut graphics_ctx_objects, + next_object_key: ref mut next_graphics_ctx_object_key, } = *graphics_ctx; let mut opt_curr_gl_ctx: Option<CurrentContextWithFns> = None; @@ -882,42 +904,82 @@ fn handle_commands( tracing::error!("Failed to create texture object: {err}"); } } - RendererCommand::DrawMesh { mesh_asset } => { + RendererCommand::CreateMesh(mesh_object_id, mesh) => { let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { tracing::error!("No GL context is current"); continue; }; - // tracing::warn!("ARGH! Drawing mesh"); - - let graphics_mesh = - match graphics_mesh_store.graphics_meshes.get(&mesh_asset.id()) { - Some(graphics_mesh) => graphics_mesh, - None => { - let Some(mesh) = assets.get(&mesh_asset) else { - tracing::trace!("Missing model asset"); - continue; - }; - - let graphics_mesh = - match GraphicsMesh::new(&curr_gl_ctx, mesh) { - Ok(graphics_mesh) => graphics_mesh, - Err(err) => { - tracing::error!( - "Failed to create {}: {err}", - type_name::<GraphicsMesh>() - ); - - continue; - } - }; - - graphics_mesh_store - .graphics_meshes - .entry(mesh_asset.id()) - .or_insert(graphics_mesh) - } - }; + if renderer_object_store.contains_with_id(&mesh_object_id) { + tracing::error!( + object_id=?mesh_object_id, + "Object store already contains a object with this ID" + ); + continue; + } + + let key = *next_graphics_ctx_object_key; + + let graphics_mesh = match GraphicsMesh::new(&curr_gl_ctx, &mesh) { + Ok(graphics_mesh) => graphics_mesh, + Err(err) => { + tracing::error!("Failed to create mesh: {err}"); + continue; + } + }; + + graphics_ctx_objects + .insert(key, GraphicsContextObject::Mesh(graphics_mesh)); + + renderer_object_store.insert( + mesh_object_id, + RendererObject::from_raw( + key, + RendererObjectKind::ImplementationSpecific, + ), + ); + + *next_graphics_ctx_object_key += 1; + } + RendererCommand::DrawMesh(mesh_object_id) => { + let Some(curr_gl_ctx) = &opt_curr_gl_ctx else { + tracing::error!("No GL context is current"); + continue; + }; + + let Some(mesh_graphics_ctx_obj_key) = renderer_object_store + .get_obj(&mesh_object_id) + .map(|obj| obj.as_raw()) + else { + tracing::error!( + object_id=?mesh_object_id, + "Object store does not contain a mesh object with this ID" + ); + continue; + }; + + let Some(mesh_graphics_ctx_obj) = + graphics_ctx_objects.get(&mesh_graphics_ctx_obj_key) + else { + tracing::error!( + object_id=?mesh_object_id, + key=mesh_graphics_ctx_obj_key, + "Graphics context does not contain a mesh object with this key" + ); + continue; + }; + + #[allow(irrefutable_let_patterns)] + let GraphicsContextObject::Mesh(graphics_mesh) = + mesh_graphics_ctx_obj + else { + tracing::error!( + object_id=?mesh_object_id, + key=mesh_graphics_ctx_obj_key, + "Graphics context object with this key is not a mesh" + ); + continue; + }; if let Err(err) = draw_mesh(&curr_gl_ctx, graphics_mesh) { tracing::error!("Failed to draw mesh: {err}"); |
