summaryrefslogtreecommitdiff
path: root/engine/src/renderer
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-04-23 03:07:01 +0200
committerHampusM <hampus@hampusmat.com>2026-04-23 03:07:01 +0200
commit6474394f49b67377c9fef66f51af61f108ae3cce (patch)
tree60acc11667e315c3226dac82f130361bbec5a834 /engine/src/renderer
parent7699a1f498dd41d9abfc907d36e37dfed7a761c0 (diff)
refactor(engine): remove support for multiple renderer contextsHEADmaster
Diffstat (limited to 'engine/src/renderer')
-rw-r--r--engine/src/renderer/main_render_pass.rs335
-rw-r--r--engine/src/renderer/object.rs52
-rw-r--r--engine/src/renderer/opengl.rs1267
3 files changed, 796 insertions, 858 deletions
diff --git a/engine/src/renderer/main_render_pass.rs b/engine/src/renderer/main_render_pass.rs
index ec490e4..1868f3d 100644
--- a/engine/src/renderer/main_render_pass.rs
+++ b/engine/src/renderer/main_render_pass.rs
@@ -1,8 +1,4 @@
-use std::any::type_name;
-
use ecs::Query;
-use ecs::actions::Actions;
-use ecs::pair::{Pair, Wildcard};
use ecs::query::term::{With, Without};
use ecs::sole::Single;
@@ -13,8 +9,6 @@ use crate::renderer::object::{Id as RendererObjectId, Store as RendererObjectSto
use crate::renderer::{
BufferClearMask as RendererBufferClearMask,
Command as RendererCommand,
- CommandQueue as RendererCommandQueue,
- CtxUsedByWindow as RendererCtxUsedByWindow,
DrawMeshOptions as RendererDrawMeshOptions,
DrawProperties as RendererDrawProperties,
DrawPropertiesUpdateFlags as RendererDrawPropertiesUpdateFlags,
@@ -22,7 +16,7 @@ use crate::renderer::{
PendingShaderBindings,
RenderPass,
RenderPasses as RendererRenderPasses,
- SurfaceSpec as RendererSurfaceSpec,
+ SurfaceSpec,
};
use crate::shader::default::ASSET_LABEL as DEFAULT_SHADER_ASSET_LABEL;
use crate::shader::{
@@ -42,18 +36,12 @@ type RenderableEntity<'a> = (
#[tracing::instrument(skip_all)]
pub fn add_main_render_passes(
- renderer_ctx_query: Query<
- (
- &RendererObjectStore,
- &[Pair<RendererCtxUsedByWindow, Wildcard>],
- ),
- (With<RendererCommandQueue>,),
- >,
renderable_query: Query<RenderableEntity<'_>, (Without<NoDraw>,)>,
+ window_surface_spec_query: Query<(&SurfaceSpec,), (With<Window>,)>,
assets: Single<Assets>,
shader_context: Single<ShaderContext>,
mut render_passes: Single<RendererRenderPasses>,
- mut actions: Actions,
+ mut object_store: Single<RendererObjectStore>,
)
{
let Some(default_shader_asset) = assets
@@ -63,217 +51,180 @@ pub fn add_main_render_passes(
return;
};
- 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 {
- let window_ent_id = ctx_used_by_window.id().target_entity();
+ for (surface_spec,) in &window_surface_spec_query {
+ let render_pass = render_passes.passes.push_front_mut(RenderPass {
+ surface_id: surface_spec.id,
+ commands: Vec::with_capacity(30),
+ draw_properties: RendererDrawProperties::default(),
+ });
- let Some(window_ent) = ctx_used_by_window.get_target_ent() else {
- tracing::error!("Window entity does not exist");
- continue;
- };
+ render_pass
+ .commands
+ .push(RendererCommand::MakeCurrent(surface_spec.id));
- if window_ent.get::<Window>().is_none() {
- tracing::debug!(
- window_entity_id=%window_ent_id,
- "Window entity does not have a {} component",
- type_name::<Window>()
- );
+ let default_texture_asset = assets
+ .get_handle_to_loaded::<Texture>(TEXTURE_WHITE_1X1_ASSET_LABEL.clone())
+ .expect("Not possible");
- actions.remove_components(
- renderer_ctx_ent_id,
- [Pair::builder()
- .relation::<RendererCtxUsedByWindow>()
- .target_id(window_ent_id)
- .build()
- .id()],
- );
+ if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
+ default_texture_asset.id(),
+ )) {
+ object_store
+ .insert_pending(RendererObjectId::Asset(default_texture_asset.id()));
- continue;
- };
+ render_pass
+ .commands
+ .push(RendererCommand::CreateTexture(default_texture_asset));
+ }
- let Some(surface_spec) = window_ent.get::<RendererSurfaceSpec>() else {
- tracing::debug!(
- window_entity_id=%window_ent_id,
- "Window entity does not have a {} component",
- type_name::<RendererSurfaceSpec>()
- );
- continue;
- };
+ render_pass.commands.push(RendererCommand::ClearBuffers(
+ RendererBufferClearMask::COLOR | RendererBufferClearMask::DEPTH,
+ ));
- render_passes.passes.push_front(RenderPass {
- renderer_ctx_ent_id,
- surface_id: surface_spec.id,
- commands: Vec::with_capacity(30),
- draw_properties: RendererDrawProperties::default(),
- });
+ for (model, draw_flags, shader, mut pending_shader_bindings) in &renderable_query
+ {
+ let shader_asset = match &shader {
+ Some(shader) => &shader.asset_handle,
+ None => &default_shader_asset,
+ };
- let render_pass = render_passes.passes.front_mut().expect("Not possible");
+ if pending_shader_bindings.as_ref().map_or_else(
+ || true,
+ |pending_shader_bindings| pending_shader_bindings.bindings.is_empty(),
+ ) {
+ continue;
+ }
- render_pass
- .commands
- .push(RendererCommand::MakeCurrent(surface_spec.id));
+ let Some(model_spec) = assets.get(&model.spec_asset) else {
+ continue;
+ };
- let default_texture_asset = assets
- .get_handle_to_loaded::<Texture>(TEXTURE_WHITE_1X1_ASSET_LABEL.clone())
- .expect("Not possible");
+ let Some(mesh_asset) = &model_spec.mesh_asset else {
+ continue;
+ };
- if !object_store
- .contains_with_id(&RendererObjectId::Asset(default_texture_asset.id()))
- {
- render_pass
- .commands
- .push(RendererCommand::CreateTexture(default_texture_asset));
+ if assets.get(mesh_asset).is_none() {
+ continue;
}
- render_pass.commands.push(RendererCommand::ClearBuffers(
- RendererBufferClearMask::COLOR | RendererBufferClearMask::DEPTH,
- ));
+ debug_assert!(model_spec.material_names.len() <= 1);
- for (model, draw_flags, shader, mut pending_shader_bindings) in
- &renderable_query
- {
- let shader_asset = match &shader {
- Some(shader) => &shader.asset_handle,
- None => &default_shader_asset,
- };
-
- if pending_shader_bindings.as_ref().map_or_else(
- || true,
- |pending_shader_bindings| pending_shader_bindings.bindings.is_empty(),
- ) {
- continue;
+ let model_material_asset = match model_spec.find_first_material(&assets) {
+ MaterialSearchResult::Found(model_material_asset) => {
+ model_material_asset.clone()
+ // Some(model_material_asset.clone())
}
-
- let Some(model_spec) = assets.get(&model.spec_asset) else {
+ MaterialSearchResult::NotFound | MaterialSearchResult::NoMaterials => {
+ // MaterialSearchResult::NotFound => {
continue;
- };
+ } // MaterialSearchResult::NoMaterials => None,
+ };
- let Some(mesh_asset) = &model_spec.mesh_asset else {
+ if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
+ shader_asset.id(),
+ )) {
+ let Some(shader_program) = shader_context.get_program(&shader_asset.id())
+ else {
+ tracing::error!(
+ "Shader context doesn't have a program for shader asset {:?}",
+ assets.get_label(&shader_asset)
+ );
continue;
};
- if assets.get(mesh_asset).is_none() {
- continue;
- }
+ object_store.insert_pending(RendererObjectId::Asset(shader_asset.id()));
+
+ render_pass
+ .commands
+ .push(RendererCommand::CreateShaderProgram(
+ RendererObjectId::Asset(shader_asset.id()),
+ shader_program.clone(),
+ ));
+ }
- debug_assert!(model_spec.material_names.len() <= 1);
+ render_pass.commands.push(RendererCommand::ActivateShader(
+ RendererObjectId::Asset(shader_asset.id()),
+ ));
- let model_material_asset = match model_spec.find_first_material(&assets) {
- MaterialSearchResult::Found(model_material_asset) => {
- model_material_asset.clone()
- // Some(model_material_asset.clone())
- }
- MaterialSearchResult::NotFound
- | MaterialSearchResult::NoMaterials => {
- // MaterialSearchResult::NotFound => {
- continue;
- } // MaterialSearchResult::NoMaterials => None,
- };
+ let Some(model_material) = assets.get(&model_material_asset) else {
+ // TODO: Handle this case since it may occur
+ unreachable!();
+ };
- if !object_store
- .contains_with_id(&RendererObjectId::Asset(shader_asset.id()))
- {
- let Some(shader_program) =
- shader_context.get_program(&shader_asset.id())
- else {
- tracing::error!(
- "Shader context doesn't have a program for shader asset {:?}",
- assets.get_label(&shader_asset)
- );
- continue;
- };
+ for texture_asset in [
+ &model_material.ambient_map,
+ &model_material.diffuse_map,
+ &model_material.specular_map,
+ ]
+ .into_iter()
+ .flatten()
+ {
+ if !object_store.contains_maybe_pending_with_id(&RendererObjectId::Asset(
+ texture_asset.id(),
+ )) {
+ object_store
+ .insert_pending(RendererObjectId::Asset(texture_asset.id()));
render_pass
.commands
- .push(RendererCommand::CreateShaderProgram(
- RendererObjectId::Asset(shader_asset.id()),
- shader_program.clone(),
- ));
+ .push(RendererCommand::CreateTexture(texture_asset.clone()));
}
+ }
- render_pass.commands.push(RendererCommand::ActivateShader(
- RendererObjectId::Asset(shader_asset.id()),
- ));
-
- let Some(model_material) = assets.get(&model_material_asset) else {
- // TODO: Handle this case since it may occur
- unreachable!();
- };
-
- for texture_asset in [
- &model_material.ambient_map,
- &model_material.diffuse_map,
- &model_material.specular_map,
- ]
- .into_iter()
- .flatten()
+ if let Some(pending_shader_bindings) = &mut pending_shader_bindings {
+ for (shader_binding_loc, shader_binding_val) in
+ pending_shader_bindings.bindings.drain(..)
{
- if !object_store
- .contains_with_id(&RendererObjectId::Asset(texture_asset.id()))
- {
- render_pass
- .commands
- .push(RendererCommand::CreateTexture(texture_asset.clone()));
- }
+ render_pass.commands.push(RendererCommand::SetShaderBinding(
+ shader_binding_loc,
+ shader_binding_val,
+ ));
}
+ }
- if let Some(pending_shader_bindings) = &mut pending_shader_bindings {
- for (shader_binding_loc, shader_binding_val) in
- pending_shader_bindings.bindings.drain(..)
- {
- render_pass.commands.push(RendererCommand::SetShaderBinding(
- shader_binding_loc,
- shader_binding_val,
- ));
- }
- }
+ if let Some(draw_flags) = draw_flags.as_deref()
+ && draw_flags.polygon_mode_config != PolygonModeConfig::default()
+ {
+ render_pass
+ .commands
+ .push(RendererCommand::UpdateDrawProperties(
+ RendererDrawProperties {
+ polygon_mode_config: draw_flags.polygon_mode_config.clone(),
+ ..Default::default()
+ },
+ RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
+ ));
+ }
- if let Some(draw_flags) = draw_flags.as_deref()
- && draw_flags.polygon_mode_config != PolygonModeConfig::default()
- {
- render_pass
- .commands
- .push(RendererCommand::UpdateDrawProperties(
- RendererDrawProperties {
- polygon_mode_config: draw_flags
- .polygon_mode_config
- .clone(),
- ..Default::default()
- },
- RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
- ));
- }
+ if !object_store
+ .contains_maybe_pending_with_id(&RendererObjectId::Asset(mesh_asset.id()))
+ {
+ object_store.insert_pending(RendererObjectId::Asset(mesh_asset.id()));
- if !object_store
- .contains_with_id(&RendererObjectId::Asset(mesh_asset.id()))
- {
- render_pass.commands.push(RendererCommand::CreateMesh {
- obj_id: RendererObjectId::Asset(mesh_asset.id()),
- mesh: None,
- usage: RendererMeshUsage::Static,
- });
- }
+ render_pass.commands.push(RendererCommand::CreateMesh {
+ obj_id: RendererObjectId::Asset(mesh_asset.id()),
+ mesh: None,
+ usage: RendererMeshUsage::Static,
+ });
+ }
- render_pass.commands.push(RendererCommand::DrawMesh(
- RendererObjectId::Asset(mesh_asset.id()),
- RendererDrawMeshOptions::default(),
- ));
+ render_pass.commands.push(RendererCommand::DrawMesh(
+ RendererObjectId::Asset(mesh_asset.id()),
+ RendererDrawMeshOptions::default(),
+ ));
- if let Some(draw_flags) = draw_flags.as_deref()
- && draw_flags.polygon_mode_config != PolygonModeConfig::default()
- {
- render_pass
- .commands
- .push(RendererCommand::UpdateDrawProperties(
- RendererDrawProperties {
- polygon_mode_config: PolygonModeConfig::default(),
- ..Default::default()
- },
- RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
- ));
- }
+ if let Some(draw_flags) = draw_flags.as_deref()
+ && draw_flags.polygon_mode_config != PolygonModeConfig::default()
+ {
+ render_pass
+ .commands
+ .push(RendererCommand::UpdateDrawProperties(
+ RendererDrawProperties {
+ polygon_mode_config: PolygonModeConfig::default(),
+ ..Default::default()
+ },
+ RendererDrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG,
+ ));
}
}
}
diff --git a/engine/src/renderer/object.rs b/engine/src/renderer/object.rs
index 13be4a4..bdff885 100644
--- a/engine/src/renderer/object.rs
+++ b/engine/src/renderer/object.rs
@@ -1,8 +1,7 @@
use std::collections::HashMap;
-use std::collections::hash_map::Entry as HashMapEntry;
use std::sync::atomic::{AtomicU64, Ordering};
-use ecs::Component;
+use ecs::Sole;
use crate::asset::Id as AssetId;
@@ -26,23 +25,31 @@ impl Id
NEXT_SEQUENTIAL_ID.fetch_add(1, Ordering::Relaxed),
))
}
+
+ pub fn into_asset_id(self) -> Option<AssetId>
+ {
+ match self {
+ Self::Asset(asset_id) => Some(asset_id),
+ Self::Sequential(_) => None,
+ }
+ }
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct SequentialId(u64);
/// Renderer object store.
-#[derive(Debug, Default, Component)]
+#[derive(Debug, Default, Sole)]
pub struct Store
{
- objects: HashMap<Id, Object>,
+ objects: HashMap<Id, Option<Object>>,
}
impl Store
{
pub fn get_obj(&self, id: &Id) -> Option<&Object>
{
- self.objects.get(id)
+ self.objects.get(id).and_then(|obj| obj.as_ref())
}
pub fn get_texture_obj(&self, id: &Id) -> Option<&Object>
@@ -67,46 +74,29 @@ impl Store
Some(obj)
}
- pub fn contains_with_id(&self, id: &Id) -> bool
+ pub fn contains_maybe_pending_with_id(&self, id: &Id) -> bool
{
self.objects.contains_key(id)
}
- pub fn insert(&mut self, id: Id, object: Object)
- {
- self.objects.insert(id, object);
- }
-
- pub fn remove(&mut self, id: &Id) -> Option<Object>
+ pub fn contains_non_pending_with_id(&self, id: &Id) -> bool
{
- self.objects.remove(id)
+ self.objects.get(id).and_then(|obj| obj.as_ref()).is_some()
}
- pub fn entry(&mut self, id: Id) -> StoreEntry<'_>
+ pub fn insert(&mut self, id: Id, object: Object)
{
- StoreEntry { inner: self.objects.entry(id) }
+ self.objects.insert(id, Some(object));
}
-}
-
-#[derive(Debug)]
-pub struct StoreEntry<'store>
-{
- inner: HashMapEntry<'store, Id, Object>,
-}
-impl<'store> StoreEntry<'store>
-{
- pub fn or_insert(self, default_obj: Object) -> &'store mut Object
+ pub fn insert_pending(&mut self, id: Id)
{
- self.inner.or_insert(default_obj)
+ self.objects.insert(id, None);
}
- pub fn or_insert_with(
- self,
- default_func: impl FnOnce() -> Object,
- ) -> &'store mut Object
+ pub fn remove(&mut self, id: &Id) -> Option<Option<Object>>
{
- self.inner.or_insert_with(default_func)
+ self.objects.remove(id)
}
}
diff --git a/engine/src/renderer/opengl.rs b/engine/src/renderer/opengl.rs
index 860416e..2283b32 100644
--- a/engine/src/renderer/opengl.rs
+++ b/engine/src/renderer/opengl.rs
@@ -4,14 +4,15 @@ use std::borrow::Cow;
use std::collections::HashMap;
use ecs::actions::Actions;
-use ecs::pair::Pair;
use ecs::query::term::Without;
use ecs::sole::Single;
-use ecs::{Component, Query};
+use ecs::{Component, Query, Sole};
+use glutin::config::Config as GlutinConfig;
use glutin::display::GetGlDisplay;
+use glutin::error::Error as GlutinError;
use glutin::prelude::{GlDisplay, PossiblyCurrentGlContext};
use glutin::surface::{
- GlSurface,
+ GlSurface as _,
Surface as GlutinSurface,
WindowSurface as GlutinWindowSurface,
};
@@ -60,7 +61,12 @@ use opengl_bindings::vertex_array::{
PrimitiveKind,
VertexArray,
};
-use opengl_bindings::{ContextWithFns, CurrentContextWithFns};
+use opengl_bindings::{
+ ContextWithFns,
+ CurrentContextWithFns,
+ MakeContextCurrentError as GlMakeContextCurrentError,
+};
+use raw_window_handle::WindowHandle;
use safer_ffi::layout::ReprC;
use zerocopy::{Immutable, IntoBytes};
@@ -82,11 +88,9 @@ use crate::renderer::opengl::glutin_compat::{
};
use crate::renderer::opengl::graphics_mesh::GraphicsMesh;
use crate::renderer::{
- ActiveDrawProperties,
BufferClearMask,
Command as RendererCommand,
CommandQueue as RendererCommandQueue,
- CtxUsedByWindow as RendererCtxUsedByWindow,
DrawMeshOptions,
DrawPropertiesUpdateFlags,
GraphicsProperties,
@@ -94,7 +98,6 @@ use crate::renderer::{
RENDER_PHASE,
SurfaceId,
SurfaceSpec,
- WindowUsingRendererCtx,
};
use crate::shader::cursor::BindingValue as ShaderBindingValue;
use crate::shader::{
@@ -109,6 +112,7 @@ use crate::texture::{
Texture,
Wrapping as TextureWrapping,
};
+use crate::util::OptionExt;
use crate::vector::{Vec2, Vec3};
use crate::windowing::Context as WindowingContext;
use crate::windowing::window::{
@@ -124,13 +128,13 @@ mod graphics_mesh;
#[derive(Debug, Component)]
struct WindowGlConfig
{
- gl_config: glutin::config::Config,
+ gl_config: GlutinConfig,
}
-#[derive(Component)]
+#[derive(Sole, Default)]
struct GraphicsContext
{
- gl_context: ContextWithFns,
+ gl_context: Option<ContextWithFns>,
surfaces: HashMap<SurfaceId, GlutinSurface<GlutinWindowSurface>>,
shader_uniform_buffer_objs:
HashMap<RendererObjectId, HashMap<u32, opengl_bindings::buffer::Buffer<u8>>>,
@@ -160,12 +164,11 @@ impl ecs::extension::Extension for Extension
collector.add_system(*POST_RENDER_PHASE, prepare_windows);
collector.add_system(*POST_RENDER_PHASE, init_window_graphics);
+
+ let _ = collector.add_sole(GraphicsContext::default());
}
}
-#[derive(Debug, Component)]
-struct SetupFailed;
-
fn prepare_windows(
window_query: Query<
(Option<&Window>, &mut WindowCreationAttributes),
@@ -173,7 +176,6 @@ fn prepare_windows(
Without<CreationReady>,
Without<WindowGlConfig>,
Without<WindowClosed>,
- Without<SetupFailed>,
),
>,
windowing_context: Single<WindowingContext>,
@@ -209,7 +211,6 @@ fn prepare_windows(
Ok(window_handle) => window_handle,
Err(err) => {
tracing::error!("Failed to get window handle: {err}");
- actions.add_components(window_ent_id, (SetupFailed,));
continue;
}
};
@@ -231,7 +232,6 @@ fn prepare_windows(
}
Err(err) => {
tracing::error!("Failed to create platform graphics display: {err}");
- actions.add_components(window_ent_id, (SetupFailed,));
continue;
}
};
@@ -248,17 +248,19 @@ fn prepare_windows(
#[tracing::instrument(skip_all)]
fn init_window_graphics(
- window_query: Query<
- (&Window, &WindowGlConfig),
- (Without<SurfaceSpec>, Without<SetupFailed>),
- >,
+ window_query: Query<(&Window, &WindowGlConfig), (Without<SurfaceSpec>,)>,
windowing_context: Single<WindowingContext>,
graphics_props: Single<GraphicsProperties>,
+ mut graphics_ctx: Single<GraphicsContext>,
mut actions: Actions,
)
{
for (window_ent_id, (window, window_gl_config)) in window_query.iter_with_euids() {
- tracing::info!("Initializing graphics for window {window_ent_id}");
+ tracing::info!(
+ window_entity_id=%window_ent_id,
+ window_title=&*window.title,
+ "Initializing graphics for window"
+ );
let display = window_gl_config.gl_config.display();
@@ -273,12 +275,10 @@ fn init_window_graphics(
entity_id = %window_ent_id,
"Windowing context does not contain window"
);
- actions.add_components(window_ent_id, (SetupFailed,));
continue;
}
Err(err) => {
tracing::error!("Failed to get window handle: {err}");
- actions.add_components(window_ent_id, (SetupFailed,));
continue;
}
};
@@ -310,31 +310,23 @@ fn init_window_graphics(
}
};
- let context = match unsafe {
- display.create_context(
+ let gl_context = match graphics_ctx.gl_context.get_or_try_insert_with_fn(|| {
+ create_gl_context(
&window_gl_config.gl_config,
- &glutin::context::ContextAttributesBuilder::new()
- .with_debug(graphics_props.debug)
- .build(Some(window_handle.as_raw())),
+ &graphics_props,
+ window_handle,
+ &surface,
)
- } {
- Ok(context) => context,
- Err(err) => {
- tracing::error!("Failed to create graphics context: {err}");
- continue;
- }
- };
-
- let gl_context = match ContextWithFns::new(context, &surface) {
- Ok(context) => context,
+ }) {
+ Ok(gl_context) => gl_context,
Err(err) => {
- tracing::error!("Failed to create graphics context: {err}");
+ tracing::error!("Failed to create GL context: {err:#?}");
continue;
}
};
let Ok(curr_gl_context) = gl_context.make_current(&surface) else {
- tracing::error!("Failed to make graphics context current");
+ tracing::error!("Failed to make GL context current");
continue;
};
@@ -384,692 +376,696 @@ fn init_window_graphics(
let surface_id = SurfaceId::new_unique();
- let renderer_ctx_ent_id = actions.spawn((
- GraphicsContext {
- gl_context,
- surfaces: HashMap::from([(surface_id, surface)]),
- shader_uniform_buffer_objs: HashMap::new(),
- objects: HashMap::new(),
- next_object_key: RendererObjectRawValue::default(),
- },
- RendererObjectStore::default(),
- RendererCommandQueue::default(),
- Pair::builder()
- .relation::<RendererCtxUsedByWindow>()
- .target_id(window_ent_id)
- .build(),
- ActiveDrawProperties::default(),
- ));
-
- actions.add_components(
- window_ent_id,
- (
- SurfaceSpec { id: surface_id },
- Pair::builder()
- .relation::<WindowUsingRendererCtx>()
- .target_id(renderer_ctx_ent_id)
- .build(),
- ),
- );
+ actions.add_components(window_ent_id, (SurfaceSpec { id: surface_id },));
+
+ graphics_ctx.surfaces.insert(surface_id, surface);
}
}
#[tracing::instrument(skip_all)]
fn handle_commands(
- renderer_ctx_query: Query<(
- &mut GraphicsContext,
- &mut RendererObjectStore,
- &mut RendererCommandQueue,
- )>,
+ mut graphics_ctx: Single<GraphicsContext>,
+ mut object_store: Single<RendererObjectStore>,
+ mut command_queue: Single<RendererCommandQueue>,
assets: Single<Assets>,
shader_context: Single<ShaderContext>,
)
{
- for (mut graphics_ctx, mut renderer_object_store, mut command_queue) in
- &renderer_ctx_query
- {
- let GraphicsContext {
- ref gl_context,
- ref mut surfaces,
- ref mut shader_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;
-
- let mut activated_gl_shader_program: Option<(RendererObjectId, GlShaderProgram)> =
- None;
-
- for command in command_queue.drain() {
- let tracing_span = tracing::info_span!("handle_cmd");
- let _tracing_span_enter = tracing_span.enter();
-
- match command {
- RendererCommand::RemoveSurface(surface_id) => {
- let Some(surface) = surfaces.remove(&surface_id) else {
- tracing::error!(surface_id=?surface_id, "Surface does not exist");
- continue;
- };
+ let GraphicsContext {
+ ref gl_context,
+ ref mut surfaces,
+ ref mut shader_uniform_buffer_objs,
+ objects: ref mut graphics_ctx_objects,
+ next_object_key: ref mut next_graphics_ctx_object_key,
+ } = *graphics_ctx;
+
+ let Some(gl_context) = gl_context else {
+ return;
+ };
- if surface.is_current(gl_context.context()) {
- opt_curr_gl_ctx = None;
+ let mut opt_curr_gl_ctx: Option<CurrentContextWithFns> = None;
- if let Err(err) = gl_context.context().make_not_current_in_place()
- {
- tracing::error!(
- "Failed to make GL context not current: {err}"
- );
- }
- }
+ let mut activated_gl_shader_program: Option<(RendererObjectId, GlShaderProgram)> =
+ None;
- drop(surface);
- }
- RendererCommand::MakeCurrent(surface_id) => {
- let Some(surface) = surfaces.get(&surface_id) else {
- tracing::error!(surface_id=?surface_id, "Surface does not exist");
- continue;
- };
+ for command in command_queue.drain() {
+ let tracing_span = tracing::info_span!("handle_cmd");
+ let _tracing_span_enter = tracing_span.enter();
- let curr_gl_ctx = match gl_context.make_current(surface) {
- Ok(current_graphics_context) => current_graphics_context,
- Err(err) => {
- tracing::error!(
- "Failed to make graphics context current: {err}"
- );
- continue;
- }
- };
+ match command {
+ RendererCommand::RemoveSurface(surface_id) => {
+ let Some(surface) = surfaces.remove(&surface_id) else {
+ tracing::error!(surface_id=?surface_id, "Surface does not exist");
+ continue;
+ };
+
+ if surface.is_current(gl_context.context()) {
+ opt_curr_gl_ctx = None;
- opt_curr_gl_ctx = Some(curr_gl_ctx);
+ if let Err(err) = gl_context.context().make_not_current_in_place() {
+ tracing::error!("Failed to make GL context not current: {err}");
+ }
}
- RendererCommand::ClearBuffers(buffer_clear_mask) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
- let mut clear_mask = GlBufferClearMask::empty();
+ drop(surface);
+ }
+ RendererCommand::MakeCurrent(surface_id) => {
+ let Some(surface) = surfaces.get(&surface_id) else {
+ tracing::error!(surface_id=?surface_id, "Surface does not exist");
+ continue;
+ };
- clear_mask.set(
- GlBufferClearMask::COLOR,
- buffer_clear_mask.contains(BufferClearMask::COLOR),
- );
+ let curr_gl_ctx = match gl_context.make_current(surface) {
+ Ok(current_graphics_context) => current_graphics_context,
+ Err(err) => {
+ tracing::error!("Failed to make graphics context current: {err}");
+ continue;
+ }
+ };
- clear_mask.set(
- GlBufferClearMask::DEPTH,
- buffer_clear_mask.contains(BufferClearMask::DEPTH),
- );
+ opt_curr_gl_ctx = Some(curr_gl_ctx);
+ }
+ RendererCommand::ClearBuffers(buffer_clear_mask) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- clear_mask.set(
- GlBufferClearMask::STENCIL,
- buffer_clear_mask.contains(BufferClearMask::STENCIL),
- );
+ let mut clear_mask = GlBufferClearMask::empty();
- clear_buffers(&curr_gl_ctx, clear_mask);
- }
- RendererCommand::SwapBuffers(surface_id) => {
- let Some(surface) = surfaces.get(&surface_id) else {
- tracing::error!(surface_id=?surface_id, "Surface does not exist");
- continue;
- };
+ clear_mask.set(
+ GlBufferClearMask::COLOR,
+ buffer_clear_mask.contains(BufferClearMask::COLOR),
+ );
- if let Err(err) = surface.swap_buffers(gl_context.context()) {
- tracing::error!("Failed to swap buffers: {err}");
- }
- }
- RendererCommand::CreateShaderProgram(
- shader_program_obj_id,
- shader_program,
- ) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
+ clear_mask.set(
+ GlBufferClearMask::DEPTH,
+ buffer_clear_mask.contains(BufferClearMask::DEPTH),
+ );
- if renderer_object_store.contains_with_id(&shader_program_obj_id) {
- tracing::error!(
- object_id=?shader_program_obj_id,
- "Object store already contains a object with this ID"
- );
- continue;
- }
+ clear_mask.set(
+ GlBufferClearMask::STENCIL,
+ buffer_clear_mask.contains(BufferClearMask::STENCIL),
+ );
- let gl_shader_program =
- match create_shader_program(&curr_gl_ctx, &shader_program) {
- Ok(gl_shader_program) => gl_shader_program,
- Err(err) => {
- tracing::error!("Failed to create shader program: {err}");
- continue;
- }
- };
+ clear_buffers(&curr_gl_ctx, clear_mask);
+ }
+ RendererCommand::SwapBuffers(surface_id) => {
+ let Some(surface) = surfaces.get(&surface_id) else {
+ tracing::error!(surface_id=?surface_id, "Surface does not exist");
+ continue;
+ };
- renderer_object_store.insert(
- shader_program_obj_id,
- RendererObject::from_raw(
- gl_shader_program.into_raw(),
- RendererObjectKind::ShaderProgram,
- ),
+ if let Err(err) = surface.swap_buffers(gl_context.context()) {
+ tracing::error!("Failed to swap buffers: {err}");
+ }
+ }
+ RendererCommand::CreateShaderProgram(
+ shader_program_obj_id,
+ shader_program,
+ ) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
+
+ if object_store.contains_non_pending_with_id(&shader_program_obj_id) {
+ tracing::error!(
+ shader_program_object_id=?shader_program_obj_id,
+ shader_asset_label=?shader_program_obj_id
+ .into_asset_id()
+ .and_then(|asset_id| assets.get_label_by_id(asset_id)),
+ "Object store already contains a object with this ID"
);
+ continue;
}
- RendererCommand::ActivateShader(shader_program_obj_id) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
- let Some(shader_program_obj) = renderer_object_store
- .get_shader_program_obj(&shader_program_obj_id)
- else {
- tracing::error!(
- "Shader object does not exist or has a wrong kind"
- );
- continue;
+ let gl_shader_program =
+ match create_shader_program(&curr_gl_ctx, &shader_program) {
+ Ok(gl_shader_program) => gl_shader_program,
+ Err(err) => {
+ tracing::error!("Failed to create shader program: {err}");
+ continue;
+ }
};
- let gl_shader_program =
- GlShaderProgram::from_raw(shader_program_obj.as_raw());
+ object_store.insert(
+ shader_program_obj_id,
+ RendererObject::from_raw(
+ gl_shader_program.into_raw(),
+ RendererObjectKind::ShaderProgram,
+ ),
+ );
+ }
+ RendererCommand::ActivateShader(shader_program_obj_id) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- gl_shader_program.activate(&curr_gl_ctx);
+ let Some(shader_program_obj) =
+ object_store.get_shader_program_obj(&shader_program_obj_id)
+ else {
+ tracing::error!("Shader object does not exist or has a wrong kind");
+ continue;
+ };
- activated_gl_shader_program =
- Some((shader_program_obj_id, gl_shader_program));
- }
- RendererCommand::SetShaderBinding(binding_location, binding_value) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
+ let gl_shader_program =
+ GlShaderProgram::from_raw(shader_program_obj.as_raw());
- let Some((activated_gl_shader_program_obj_id, _)) =
- &activated_gl_shader_program
- else {
- tracing::error!("No shader program is activated");
- continue;
- };
+ gl_shader_program.activate(&curr_gl_ctx);
- if let ShaderBindingValue::Texture(texture_asset) = &binding_value {
- let Some(texture_obj) = renderer_object_store.get_texture_obj(
- &RendererObjectId::Asset(texture_asset.id()),
- ) else {
- tracing::error!(
- "Texture {:?} does not exist in renderer object store",
- assets.get_label(texture_asset)
- );
- continue;
- };
+ activated_gl_shader_program =
+ Some((shader_program_obj_id, gl_shader_program));
+ }
+ RendererCommand::SetShaderBinding(binding_location, binding_value) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- let gl_texture = GlTexture::from_raw(texture_obj.as_raw());
+ let Some((activated_gl_shader_program_obj_id, _)) =
+ &activated_gl_shader_program
+ else {
+ tracing::error!("No shader program is activated");
+ continue;
+ };
- gl_texture.bind_to_texture_unit(
- curr_gl_ctx,
- binding_location.binding_index,
+ if let ShaderBindingValue::Texture(texture_asset) = &binding_value {
+ let Some(texture_obj) = object_store
+ .get_texture_obj(&RendererObjectId::Asset(texture_asset.id()))
+ else {
+ tracing::error!(
+ "Texture {:?} does not exist in renderer object store",
+ assets.get_label(texture_asset)
);
-
- // gl_shader_program.set_uniform_at_location(
- // curr_gl_ctx,
- // GlUniformLocation::from_number(
- // binding_location.binding_index as i32,
- // ),
- // &binding_location.binding_index,
- // );
-
continue;
- }
+ };
+
+ let gl_texture = GlTexture::from_raw(texture_obj.as_raw());
- let binding_index = binding_location.binding_index;
-
- let uniform_buffer_objs = shader_uniform_buffer_objs
- .entry(*activated_gl_shader_program_obj_id)
- .or_default();
-
- let uniform_buffer =
- uniform_buffer_objs.entry(binding_index).or_insert_with(|| {
- let uniform_buf =
- opengl_bindings::buffer::Buffer::<u8>::new(curr_gl_ctx);
-
- uniform_buf
- .init(
- curr_gl_ctx,
- binding_location.binding_size,
- opengl_bindings::buffer::Usage::Dynamic,
- )
- .unwrap();
-
- uniform_buf
- });
-
- // The index into the uniform buffer binding target is for whatever
- // shader program is currently bound so the uniform buffer object has
- // to be re-bound so that a uniform buffer from another shader isn't
- // used
- uniform_buffer.bind_to_indexed_target(
+ gl_texture.bind_to_texture_unit(
curr_gl_ctx,
- opengl_bindings::buffer::BindingTarget::UniformBuffer,
- binding_index as u32,
+ binding_location.binding_index,
);
- let fvec3_value;
+ // gl_shader_program.set_uniform_at_location(
+ // curr_gl_ctx,
+ // GlUniformLocation::from_number(
+ // binding_location.binding_index as i32,
+ // ),
+ // &binding_location.binding_index,
+ // );
- uniform_buffer
- .store_at_byte_offset(
- curr_gl_ctx,
- binding_location.byte_offset,
- match binding_value {
- ShaderBindingValue::Uint(ref value) => value.as_bytes(),
- ShaderBindingValue::Int(ref value) => value.as_bytes(),
- ShaderBindingValue::Float(ref value) => value.as_bytes(),
- ShaderBindingValue::FVec3(value) => {
- fvec3_value = CF32Vec3::from(value);
-
- fvec3_value.as_bytes()
- }
- ShaderBindingValue::FMat4x4(ref value) => {
- value.items().as_bytes()
- }
- ShaderBindingValue::Texture(_) => unreachable!(),
- },
- )
- .unwrap();
+ continue;
}
- RendererCommand::CreateTexture(texture_asset) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
- if let Err(err) = create_texture_object(
+ let binding_index = binding_location.binding_index;
+
+ let uniform_buffer_objs = shader_uniform_buffer_objs
+ .entry(*activated_gl_shader_program_obj_id)
+ .or_default();
+
+ let uniform_buffer =
+ uniform_buffer_objs.entry(binding_index).or_insert_with(|| {
+ let uniform_buf =
+ opengl_bindings::buffer::Buffer::<u8>::new(curr_gl_ctx);
+
+ uniform_buf
+ .init(
+ curr_gl_ctx,
+ binding_location.binding_size,
+ opengl_bindings::buffer::Usage::Dynamic,
+ )
+ .unwrap();
+
+ uniform_buf
+ });
+
+ // The index into the uniform buffer binding target is for whatever
+ // shader program is currently bound so the uniform buffer object has
+ // to be re-bound so that a uniform buffer from another shader isn't
+ // used
+ uniform_buffer.bind_to_indexed_target(
+ curr_gl_ctx,
+ opengl_bindings::buffer::BindingTarget::UniformBuffer,
+ binding_index as u32,
+ );
+
+ let fvec3_value;
+
+ uniform_buffer
+ .store_at_byte_offset(
curr_gl_ctx,
- &mut renderer_object_store,
- &assets,
- &texture_asset,
- ) {
- tracing::error!("Failed to create texture object: {err}");
- }
+ binding_location.byte_offset,
+ match binding_value {
+ ShaderBindingValue::Uint(ref value) => value.as_bytes(),
+ ShaderBindingValue::Int(ref value) => value.as_bytes(),
+ ShaderBindingValue::Float(ref value) => value.as_bytes(),
+ ShaderBindingValue::FVec3(value) => {
+ fvec3_value = CF32Vec3::from(value);
+
+ fvec3_value.as_bytes()
+ }
+ ShaderBindingValue::FMat4x4(ref value) => {
+ value.items().as_bytes()
+ }
+ ShaderBindingValue::Texture(_) => unreachable!(),
+ },
+ )
+ .unwrap();
+ }
+ RendererCommand::CreateTexture(texture_asset) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
+
+ if let Err(err) = create_texture_object(
+ curr_gl_ctx,
+ &mut object_store,
+ &assets,
+ &texture_asset,
+ ) {
+ tracing::error!("Failed to create texture object: {err}");
}
- RendererCommand::CreateMesh {
- obj_id: mesh_object_id,
- mesh,
- usage: mesh_usage,
- } => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
+ }
+ RendererCommand::CreateMesh {
+ obj_id: mesh_object_id,
+ mesh,
+ usage: mesh_usage,
+ } => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- 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;
- }
+ if object_store.contains_non_pending_with_id(&mesh_object_id) {
+ tracing::error!(
+ mesh_object_id=?mesh_object_id,
+ mesh_asset_label=?mesh_object_id
+ .into_asset_id()
+ .and_then(|asset_id| assets.get_label_by_id(asset_id)),
+ "Object store already contains a object with this ID"
+ );
+ continue;
+ }
- let Some((RendererObjectId::Asset(curr_shader_program_asset_id), _)) =
- &activated_gl_shader_program
- else {
- tracing::error!("No shader program is activated");
- continue;
- };
+ let Some((RendererObjectId::Asset(curr_shader_program_asset_id), _)) =
+ &activated_gl_shader_program
+ else {
+ tracing::error!("No shader program is activated");
+ continue;
+ };
- let curr_shader_program_metadata = shader_context
- .get_program_metadata(curr_shader_program_asset_id)
- .expect("Not possible");
+ let curr_shader_program_metadata = shader_context
+ .get_program_metadata(curr_shader_program_asset_id)
+ .expect("Not possible");
- let Some(vertex_desc) = &curr_shader_program_metadata.vertex_desc
- else {
- tracing::error!(
- "Current shader program does not have a vertex description"
- );
- continue;
- };
+ let Some(vertex_desc) = &curr_shader_program_metadata.vertex_desc else {
+ tracing::error!(
+ "Current shader program does not have a vertex description"
+ );
+ continue;
+ };
- let key = *next_graphics_ctx_object_key;
-
- let mesh = match mesh_object_id {
- RendererObjectId::Asset(mesh_asset_id) => match mesh.as_ref() {
- Some(mesh) => mesh,
- None => {
- let Some(mesh) =
- assets.get(&AssetHandle::from_id(mesh_asset_id))
- else {
- tracing::error!(
- asset_id=?mesh_asset_id,
- "Mesh asset does not exist"
- );
- continue;
- };
-
- mesh
- }
- },
- RendererObjectId::Sequential(_) => {
- let Some(mesh) = mesh.as_ref() else {
+ let key = *next_graphics_ctx_object_key;
+
+ let mesh = match mesh_object_id {
+ RendererObjectId::Asset(mesh_asset_id) => match mesh.as_ref() {
+ Some(mesh) => mesh,
+ None => {
+ let Some(mesh) =
+ assets.get(&AssetHandle::from_id(mesh_asset_id))
+ else {
tracing::error!(
- object_id=?mesh_object_id,
- "Object ID is sequential but no mesh data is given"
+ asset_id=?mesh_asset_id,
+ "Mesh asset does not exist"
);
continue;
};
mesh
}
- };
-
- let graphics_mesh = match GraphicsMesh::new(
- &curr_gl_ctx,
- &mesh,
- mesh_usage,
- &vertex_desc,
- ) {
- Ok(graphics_mesh) => graphics_mesh,
- Err(err) => {
- tracing::error!("Failed to create mesh: {err}");
+ },
+ RendererObjectId::Sequential(_) => {
+ let Some(mesh) = mesh.as_ref() else {
+ tracing::error!(
+ object_id=?mesh_object_id,
+ "Object ID is sequential but no mesh data is given"
+ );
continue;
- }
- };
+ };
- graphics_ctx_objects.insert(
- key,
- GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id: RendererObjectId::Asset(
- *curr_shader_program_asset_id,
- ),
- },
- );
+ mesh
+ }
+ };
+
+ let graphics_mesh = match GraphicsMesh::new(
+ &curr_gl_ctx,
+ &mesh,
+ mesh_usage,
+ &vertex_desc,
+ ) {
+ Ok(graphics_mesh) => graphics_mesh,
+ Err(err) => {
+ tracing::error!("Failed to create mesh: {err}");
+ continue;
+ }
+ };
- renderer_object_store.insert(
- mesh_object_id,
- RendererObject::from_raw(
- key,
- RendererObjectKind::ImplementationSpecific,
+ graphics_ctx_objects.insert(
+ key,
+ GraphicsContextObject::Mesh {
+ mesh: graphics_mesh,
+ compatible_shader_program_obj_id: RendererObjectId::Asset(
+ *curr_shader_program_asset_id,
),
- );
+ },
+ );
- *next_graphics_ctx_object_key += 1;
- }
- RendererCommand::UpdateMesh {
- obj_id: mesh_object_id,
- mesh,
- usage: mesh_usage,
- } => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
+ object_store.insert(
+ mesh_object_id,
+ RendererObject::from_raw(
+ key,
+ RendererObjectKind::ImplementationSpecific,
+ ),
+ );
- 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;
- };
+ *next_graphics_ctx_object_key += 1;
+ }
+ RendererCommand::UpdateMesh {
+ obj_id: mesh_object_id,
+ mesh,
+ usage: mesh_usage,
+ } => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- let Some(mesh_graphics_ctx_obj) =
- graphics_ctx_objects.get_mut(&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;
- };
+ let Some(mesh_graphics_ctx_obj_key) = 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;
+ };
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id: _,
- } = 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;
- };
+ let Some(mesh_graphics_ctx_obj) =
+ graphics_ctx_objects.get_mut(&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 {
+ mesh: graphics_mesh,
+ compatible_shader_program_obj_id: _,
+ } = 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) = graphics_mesh.update(curr_gl_ctx, &mesh, mesh_usage)
- {
- tracing::error!("Failed to update mesh: {err}");
- }
+ if let Err(err) = graphics_mesh.update(curr_gl_ctx, &mesh, mesh_usage) {
+ tracing::error!("Failed to update mesh: {err}");
}
- RendererCommand::RemoveMesh(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
- .remove(&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.remove(&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;
- };
+ }
+ RendererCommand::RemoveMesh(mesh_object_id) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh { mesh: mut 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;
- };
+ let Some(mesh_graphics_ctx_obj_key) = object_store
+ .remove(&mesh_object_id)
+ .flatten()
+ .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;
+ };
- graphics_mesh.destroy(curr_gl_ctx);
- }
- RendererCommand::DrawMesh(mesh_object_id, draw_mesh_opts) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
+ let Some(mesh_graphics_ctx_obj) =
+ graphics_ctx_objects.remove(&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;
+ };
- 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;
- };
+ #[allow(irrefutable_let_patterns)]
+ let GraphicsContextObject::Mesh { mesh: mut 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;
+ };
- 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;
- };
+ graphics_mesh.destroy(curr_gl_ctx);
+ }
+ RendererCommand::DrawMesh(mesh_object_id, draw_mesh_opts) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- #[allow(irrefutable_let_patterns)]
- let GraphicsContextObject::Mesh {
- mesh: graphics_mesh,
- compatible_shader_program_obj_id,
- } = 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;
- };
+ let Some(mesh_graphics_ctx_obj_key) = 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;
+ };
- if Some(compatible_shader_program_obj_id)
- != activated_gl_shader_program.as_ref().map(
- |(activated_gl_shader_program_obj_id, _)| {
- activated_gl_shader_program_obj_id
- },
- )
- {
- tracing::error!(concat!(
- "Activated shader program is not the ",
- "compatible shader program of the mesh"
- ));
- 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 {
+ mesh: graphics_mesh,
+ compatible_shader_program_obj_id,
+ } = 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, &draw_mesh_opts)
- {
- tracing::error!("Failed to draw mesh: {err}");
- };
+ if Some(compatible_shader_program_obj_id)
+ != activated_gl_shader_program.as_ref().map(
+ |(activated_gl_shader_program_obj_id, _)| {
+ activated_gl_shader_program_obj_id
+ },
+ )
+ {
+ tracing::error!(concat!(
+ "Activated shader program is not the ",
+ "compatible shader program of the mesh"
+ ));
+ continue;
}
- RendererCommand::UpdateDrawProperties(
- draw_props,
- draw_props_update_flags,
- ) => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG)
- {
- opengl_bindings::misc::set_polygon_mode(
- &curr_gl_ctx,
- draw_props.polygon_mode_config.face,
- draw_props.polygon_mode_config.mode,
- );
- }
+ if let Err(err) = draw_mesh(&curr_gl_ctx, graphics_mesh, &draw_mesh_opts)
+ {
+ tracing::error!("Failed to draw mesh: {err}");
+ };
+ }
+ RendererCommand::UpdateDrawProperties(
+ draw_props,
+ draw_props_update_flags,
+ ) => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::BLENDING_ENABLED)
- {
- set_enabled(
- curr_gl_ctx,
- Capability::Blend,
- draw_props.blending_enabled,
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::POLYGON_MODE_CONFIG)
+ {
+ opengl_bindings::misc::set_polygon_mode(
+ &curr_gl_ctx,
+ draw_props.polygon_mode_config.face,
+ draw_props.polygon_mode_config.mode,
+ );
+ }
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::BLENDING_CONFIG)
- {
- gl_blending_configure(
- curr_gl_ctx,
- GlBlendingConfig::default()
- .with_source_factor(blending_factor_to_gl(
- draw_props.blending_config.source_factor,
- ))
- .with_destination_factor(blending_factor_to_gl(
- draw_props.blending_config.destination_factor,
- ))
- .with_equation(blending_equation_to_gl(
- draw_props.blending_config.equation,
- )),
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::BLENDING_ENABLED)
+ {
+ set_enabled(
+ curr_gl_ctx,
+ Capability::Blend,
+ draw_props.blending_enabled,
+ );
+ }
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::DEPTH_TEST_ENABLED)
- {
- set_enabled(
- curr_gl_ctx,
- Capability::DepthTest,
- draw_props.depth_test_enabled,
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::BLENDING_CONFIG)
+ {
+ gl_blending_configure(
+ curr_gl_ctx,
+ GlBlendingConfig::default()
+ .with_source_factor(blending_factor_to_gl(
+ draw_props.blending_config.source_factor,
+ ))
+ .with_destination_factor(blending_factor_to_gl(
+ draw_props.blending_config.destination_factor,
+ ))
+ .with_equation(blending_equation_to_gl(
+ draw_props.blending_config.equation,
+ )),
+ );
+ }
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::SCISSOR_TEST_ENABLED)
- {
- set_enabled(
- curr_gl_ctx,
- Capability::ScissorTest,
- draw_props.scissor_test_enabled,
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::DEPTH_TEST_ENABLED)
+ {
+ set_enabled(
+ curr_gl_ctx,
+ Capability::DepthTest,
+ draw_props.depth_test_enabled,
+ );
+ }
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::SCISSOR_BOX)
- {
- gl_define_scissor_box(
- curr_gl_ctx,
- draw_props.scissor_box.lower_left_corner_pos.into(),
- draw_props
- .scissor_box
- .size
- .unwrap_or_else(|| {
- let (_, viewport_size) = gl_get_viewport(curr_gl_ctx);
-
- Dimens::<u16> {
- width: viewport_size
- .width
- .try_into()
- .expect("Viewport width too large"),
- height: viewport_size
- .height
- .try_into()
- .expect("Viewport height too large"),
- }
- })
- .into(),
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::SCISSOR_TEST_ENABLED)
+ {
+ set_enabled(
+ curr_gl_ctx,
+ Capability::ScissorTest,
+ draw_props.scissor_test_enabled,
+ );
+ }
- if draw_props_update_flags
- .contains(DrawPropertiesUpdateFlags::FACE_CULLING_ENABLED)
- {
- set_enabled(
- curr_gl_ctx,
- Capability::CullFace,
- draw_props.face_culling_enabled,
- );
- }
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::SCISSOR_BOX)
+ {
+ gl_define_scissor_box(
+ curr_gl_ctx,
+ draw_props.scissor_box.lower_left_corner_pos.into(),
+ draw_props
+ .scissor_box
+ .size
+ .unwrap_or_else(|| {
+ let (_, viewport_size) = gl_get_viewport(curr_gl_ctx);
+
+ Dimens::<u16> {
+ width: viewport_size
+ .width
+ .try_into()
+ .expect("Viewport width too large"),
+ height: viewport_size
+ .height
+ .try_into()
+ .expect("Viewport height too large"),
+ }
+ })
+ .into(),
+ );
}
- RendererCommand::SetViewport {
- size: viewport_size,
- position: viewport_position,
- } => {
- let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
- tracing::error!("No GL context is current");
- continue;
- };
- if let Err(err) = gl_set_viewport(
+ if draw_props_update_flags
+ .contains(DrawPropertiesUpdateFlags::FACE_CULLING_ENABLED)
+ {
+ set_enabled(
curr_gl_ctx,
- &viewport_position.into(),
- &viewport_size.into(),
- ) {
- tracing::error!("Failed to set viewport: {err}");
- }
+ Capability::CullFace,
+ draw_props.face_culling_enabled,
+ );
+ }
+ }
+ RendererCommand::SetViewport {
+ size: viewport_size,
+ position: viewport_position,
+ } => {
+ let Some(curr_gl_ctx) = &opt_curr_gl_ctx else {
+ tracing::error!("No GL context is current");
+ continue;
+ };
+
+ if let Err(err) = gl_set_viewport(
+ curr_gl_ctx,
+ &viewport_position.into(),
+ &viewport_size.into(),
+ ) {
+ tracing::error!("Failed to set viewport: {err}");
}
}
}
}
}
+fn create_gl_context(
+ gl_config: &GlutinConfig,
+ graphics_props: &GraphicsProperties,
+ window_handle: WindowHandle<'_>,
+ surface: &GlutinSurface<GlutinWindowSurface>,
+) -> Result<ContextWithFns, CreateGlContextError>
+{
+ let display = gl_config.display();
+
+ let glutin_context = unsafe {
+ display.create_context(
+ gl_config,
+ &glutin::context::ContextAttributesBuilder::new()
+ .with_debug(graphics_props.debug)
+ .build(Some(window_handle.as_raw())),
+ )
+ }
+ .map_err(CreateGlContextError::CreateGlutinContext)?;
+
+ ContextWithFns::new(glutin_context, &surface)
+ .map_err(CreateGlContextError::MakeContextCurrent)
+}
+
+#[derive(Debug, thiserror::Error)]
+enum CreateGlContextError
+{
+ #[error("Glutin context creation failed")]
+ CreateGlutinContext(#[source] GlutinError),
+
+ #[error("Making GL context current failed")]
+ MakeContextCurrent(#[source] GlMakeContextCurrentError),
+}
+
#[tracing::instrument(skip_all)]
fn create_texture_object(
curr_gl_ctx: &CurrentContextWithFns<'_>,
@@ -1080,9 +1076,10 @@ fn create_texture_object(
{
let object_id = RendererObjectId::Asset(texture_asset.id());
- if renderer_object_store.contains_with_id(&object_id) {
+ if renderer_object_store.contains_non_pending_with_id(&object_id) {
tracing::error!(
texture_object_id=?object_id,
+ texture_asset_label=?assets.get_label(texture_asset),
"Renderer object store already contains object with this ID"
);
return Ok(());