summaryrefslogtreecommitdiff
path: root/engine/src/renderer/opengl.rs
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/renderer/opengl.rs')
-rw-r--r--engine/src/renderer/opengl.rs1267
1 files changed, 632 insertions, 635 deletions
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(());