summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-03-21 17:54:55 +0100
committerHampusM <hampus@hampusmat.com>2026-03-21 17:54:55 +0100
commit4f06675fa051e4b2f54960f76b75060c27ea8b7d (patch)
treec1c4597146e90ee34f6cef20586d59d6e03be451
parentd9bc1cc503c9a579dab263ed358a066053dbb495 (diff)
refactor(engine): add dedicated mesh creation renderer command
-rw-r--r--engine/src/renderer.rs21
-rw-r--r--engine/src/renderer/object.rs10
-rw-r--r--engine/src/renderer/opengl.rs156
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}");