summaryrefslogtreecommitdiff
path: root/engine
diff options
context:
space:
mode:
authorHampusM <hampus@hampusmat.com>2026-08-11 14:11:10 +0200
committerHampusM <hampus@hampusmat.com>2026-08-11 17:04:29 +0200
commit99e69bc233caa9b73a5297286487476f44f539f9 (patch)
tree955cd549adac7b8173c407354f7644c317e41e13 /engine
parent8a62f8c8737d59df11a9627fc031248ddbf3fe6c (diff)
feat(engine): set GPU vertex attrs on DrawMesh command if necessaryHEADmaster
Diffstat (limited to 'engine')
-rw-r--r--engine/src/rendering/backend/opengl.rs164
-rw-r--r--engine/src/rendering/backend/opengl/graphics_mesh.rs185
-rw-r--r--engine/src/rendering/shader.rs191
3 files changed, 338 insertions, 202 deletions
diff --git a/engine/src/rendering/backend/opengl.rs b/engine/src/rendering/backend/opengl.rs
index 12aaaf0..0dfe960 100644
--- a/engine/src/rendering/backend/opengl.rs
+++ b/engine/src/rendering/backend/opengl.rs
@@ -47,7 +47,6 @@ use opengl_bindings::shader::{
Kind as ShaderKind,
Program as GlShaderProgram,
Shader as GlShader,
- // UniformLocation as GlUniformLocation,
};
use opengl_bindings::texture::{
ColorSpace as GlTextureColorSpace,
@@ -101,9 +100,9 @@ use crate::rendering::shader::cursor::{
BindingValue as ShaderBindingValue,
};
use crate::rendering::shader::{
- Context as ShaderContext,
Error as ShaderError,
Program as ShaderProgram,
+ ProgramMetadata as ShaderProgramMetadata,
Stage as ShaderStage,
};
use crate::rendering::{
@@ -173,7 +172,12 @@ enum GraphicsContextObject
Mesh
{
mesh: GraphicsMesh,
- compatible_shader_program_obj_id: ObjectId,
+ vertex_attrs_updated_for_shader: Option<ObjectId>,
+ },
+ Shader
+ {
+ program: GlShaderProgram,
+ program_metadata: ShaderProgramMetadata,
},
}
@@ -443,7 +447,6 @@ fn handle_commands(
mut object_store: Single<ObjectStore>,
mut command_queue: Single<CommandQueue>,
assets: Single<Assets>,
- shader_context: Single<ShaderContext>,
) -> Result<(), crate::Error>
{
let Ok(graphics_ctx) = graphics_ctx.get_mut() else {
@@ -453,7 +456,6 @@ fn handle_commands(
let object_store = object_store.get_mut()?;
let command_queue = command_queue.get_mut()?;
let assets = assets.get()?;
- let shader_context = shader_context.get()?;
let GraphicsContext {
ref gl_context,
@@ -467,7 +469,11 @@ fn handle_commands(
return Ok(());
};
- let mut activated_gl_shader_program: Option<(ObjectId, GlShaderProgram)> = None;
+ let mut activated_gl_shader_program: Option<(
+ ObjectId,
+ GlShaderProgram,
+ ShaderProgramMetadata,
+ )> = None;
for command in command_queue.drain() {
let tracing_span = tracing::info_span!(
@@ -593,35 +599,80 @@ fn handle_commands(
}
};
+ let key = *next_graphics_ctx_object_key;
+
+ graphics_ctx_objects.insert(
+ key,
+ GraphicsContextObject::Shader {
+ program: gl_shader_program,
+ program_metadata: shader_program.metadata().clone(),
+ },
+ );
+
object_store.insert(
shader_program_obj_id,
- Object::from_raw(
- gl_shader_program.into_raw(),
- ObjectKind::ShaderProgram,
- ),
+ Object::from_raw(key, ObjectKind::ShaderProgram),
);
+
+ *next_graphics_ctx_object_key += 1;
}
Command::ActivateShader(shader_program_obj_id) => {
let Some(shader_program_obj) =
- object_store.get_shader_program_obj(&shader_program_obj_id)
+ object_store.get_obj(&shader_program_obj_id)
else {
- tracing::error!("Shader object does not exist or has a wrong kind");
+ tracing::error!(
+ object_id = ?shader_program_obj_id,
+ "Object does not exist"
+ );
+
continue;
};
- let gl_shader_program =
- GlShaderProgram::from_raw(shader_program_obj.as_raw());
+ if shader_program_obj.kind() != ObjectKind::ShaderProgram {
+ tracing::error!(
+ object_id = ?shader_program_obj_id,
+ actual_kind = ?shader_program_obj.kind(),
+ "Invalid object kind: not a shader program"
+ );
- gl_shader_program.activate(gl_context);
+ continue;
+ }
+
+ let key = shader_program_obj.as_raw();
- activated_gl_shader_program =
- Some((shader_program_obj_id, gl_shader_program));
+ let Some(graphics_ctx_obj) = graphics_ctx_objects.get(&key) else {
+ tracing::error!(
+ object_id = ?shader_program_obj_id,
+ key = key,
+ "Object not found in graphics context object store"
+ );
+ continue;
+ };
+
+ let GraphicsContextObject::Shader { program, program_metadata } =
+ graphics_ctx_obj
+ else {
+ tracing::error!(
+ object_id = ?shader_program_obj_id,
+ key = key,
+ "Graphics context object is not a shader"
+ );
+ continue;
+ };
+
+ program.activate(gl_context);
+
+ activated_gl_shader_program = Some((
+ shader_program_obj_id,
+ program.clone(),
+ program_metadata.clone(),
+ ));
}
Command::SetShaderBinding(ShaderBinding {
location: binding_location,
value: binding_value,
}) => {
- let Some((activated_gl_shader_program_obj_id, _)) =
+ let Some((activated_gl_shader_program_obj_id, _, _)) =
&activated_gl_shader_program
else {
tracing::error!("No shader program is activated");
@@ -786,24 +837,6 @@ fn handle_commands(
continue;
}
- let Some((ObjectId::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 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 {
@@ -821,12 +854,8 @@ fn handle_commands(
AssetOrValue::Value(mesh) => mesh,
};
- let graphics_mesh = match GraphicsMesh::new(
- gl_context,
- &mesh,
- mesh_usage,
- &vertex_desc,
- ) {
+ let graphics_mesh = match GraphicsMesh::new(gl_context, &mesh, mesh_usage)
+ {
Ok(graphics_mesh) => graphics_mesh,
Err(err) => {
tracing::error!("Failed to create mesh: {err}");
@@ -838,9 +867,7 @@ fn handle_commands(
key,
GraphicsContextObject::Mesh {
mesh: graphics_mesh,
- compatible_shader_program_obj_id: ObjectId::Asset(
- *curr_shader_program_asset_id,
- ),
+ vertex_attrs_updated_for_shader: None,
},
);
@@ -881,7 +908,7 @@ fn handle_commands(
#[allow(irrefutable_let_patterns)]
let GraphicsContextObject::Mesh {
mesh: graphics_mesh,
- compatible_shader_program_obj_id: _,
+ vertex_attrs_updated_for_shader: _,
} = mesh_graphics_ctx_obj
else {
tracing::error!(
@@ -947,7 +974,7 @@ fn handle_commands(
};
let Some(mesh_graphics_ctx_obj) =
- graphics_ctx_objects.get(&mesh_graphics_ctx_obj_key)
+ graphics_ctx_objects.get_mut(&mesh_graphics_ctx_obj_key)
else {
tracing::error!(
object_id=?mesh_object_id,
@@ -957,10 +984,9 @@ fn handle_commands(
continue;
};
- #[allow(irrefutable_let_patterns)]
let GraphicsContextObject::Mesh {
mesh: graphics_mesh,
- compatible_shader_program_obj_id,
+ vertex_attrs_updated_for_shader,
} = mesh_graphics_ctx_obj
else {
tracing::error!(
@@ -971,18 +997,36 @@ fn handle_commands(
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"
- ));
+ let Some((shader_program_obj_id, _, shader_program_metadata)) =
+ &activated_gl_shader_program
+ else {
+ tracing::error!("No shader program is activated");
continue;
+ };
+
+ if vertex_attrs_updated_for_shader.is_none_or(
+ |vertex_attrs_updated_for_shader| {
+ vertex_attrs_updated_for_shader != *shader_program_obj_id
+ },
+ ) {
+ let Some(shader_program_vertex_desc) =
+ &shader_program_metadata.vertex_desc
+ else {
+ tracing::error!(
+ "Activated shader program does not have a vertex description"
+ );
+ continue;
+ };
+
+ if let Err(err) = graphics_mesh.update_vertex_attrs_for_shader(
+ gl_context,
+ shader_program_vertex_desc,
+ ) {
+ tracing::error!("Cannot draw mesh: {err}");
+ continue;
+ }
+
+ *vertex_attrs_updated_for_shader = Some(*shader_program_obj_id);
}
if let Err(err) = draw_mesh(gl_context, graphics_mesh, &draw_mesh_opts) {
diff --git a/engine/src/rendering/backend/opengl/graphics_mesh.rs b/engine/src/rendering/backend/opengl/graphics_mesh.rs
index 6d5c248..a1c903b 100644
--- a/engine/src/rendering/backend/opengl/graphics_mesh.rs
+++ b/engine/src/rendering/backend/opengl/graphics_mesh.rs
@@ -1,3 +1,5 @@
+use std::hint::cold_path;
+
use opengl_bindings::buffer::{Buffer as GlBuffer, Usage as GlBufferUsage};
use opengl_bindings::vertex_array::{
AttributeFormat as GlVertexArrayAttributeFormat,
@@ -8,15 +10,20 @@ use opengl_bindings::vertex_array::{
};
use opengl_bindings::MaybeCurrentContextWithFns as GlCurrentContextWithFns;
+use crate::mesh::vertex_buffer::VertexAttrProperties as MeshVertexAttrProperties;
use crate::mesh::{Mesh, VertexAttrType};
use crate::rendering::shader::VertexDescription as ShaderVertexDescription;
use crate::rendering::MeshUsage;
+const VERTEX_BUF_BINDING_INDEX: u32 = 0;
+
#[derive(Debug)]
pub struct GraphicsMesh
{
/// Vertex and index buffer has to live as long as the vertex array
vertex_buffer: GlBuffer<u8>,
+ vertex_attr_props: Vec<MeshVertexAttrProperties>,
+ last_used_vertex_attr_cnt: u32,
pub index_buffer: Option<GlBuffer<u32>>,
pub element_cnt: u32,
pub vertex_arr: GlVertexArray,
@@ -29,7 +36,6 @@ impl GraphicsMesh
current_context: &GlCurrentContextWithFns,
mesh: &Mesh,
mesh_usage: MeshUsage,
- vertex_desc: &ShaderVertexDescription,
) -> Result<Self, Error>
{
let buffer_usage = mesh_usage_to_gl_buffer_usage(mesh_usage);
@@ -41,11 +47,9 @@ impl GraphicsMesh
.store(current_context, mesh.vertex_buf().as_bytes(), buffer_usage)
.map_err(Error::StoreVerticesFailed)?;
- let vertex_buf_binding_index = 0;
-
if let Err(err) = vertex_arr.bind_vertex_buffer(
current_context,
- vertex_buf_binding_index,
+ VERTEX_BUF_BINDING_INDEX,
&vertex_buffer,
GlVertexArrayVertexBufferSpec {
offset: 0,
@@ -69,48 +73,6 @@ impl GraphicsMesh
}
}
- for vertex_attr_props in mesh.vertex_buf().vertex_attr_props() {
- let vertex_field_desc = vertex_desc
- .fields
- .iter()
- .find(|vertex_field_desc| {
- *vertex_field_desc.name == vertex_attr_props.name
- })
- .unwrap();
-
- let attrib_index: u32 =
- vertex_field_desc.varying_input_offset.try_into().unwrap();
-
- vertex_arr.enable_attrib(current_context, attrib_index);
-
- vertex_arr.set_attrib_format(
- current_context,
- attrib_index,
- match &vertex_attr_props.ty {
- VertexAttrType::Float32 => GlVertexArrayAttributeFormat {
- data_type: GlVertexArrayDataType::Float,
- count: 1,
- normalized: false,
- offset: vertex_attr_props.byte_offset.try_into().unwrap(),
- },
- VertexAttrType::Float32Array { length } => {
- GlVertexArrayAttributeFormat {
- data_type: GlVertexArrayDataType::Float,
- count: (*length).try_into().unwrap(),
- normalized: false,
- offset: vertex_attr_props.byte_offset.try_into().unwrap(),
- }
- }
- },
- );
-
- vertex_arr.set_attrib_vertex_buf_binding(
- current_context,
- attrib_index,
- vertex_buf_binding_index,
- );
- }
-
if let Some(indices) = mesh.indices() {
let index_buffer = GlBuffer::new(current_context);
@@ -122,6 +84,8 @@ impl GraphicsMesh
return Ok(Self {
vertex_buffer: vertex_buffer,
+ vertex_attr_props: mesh.vertex_buf().vertex_attr_props().to_vec(),
+ last_used_vertex_attr_cnt: 0,
index_buffer: Some(index_buffer),
element_cnt: indices
.len()
@@ -133,6 +97,8 @@ impl GraphicsMesh
Ok(Self {
vertex_buffer: vertex_buffer,
+ vertex_attr_props: mesh.vertex_buf().vertex_attr_props().to_vec(),
+ last_used_vertex_attr_cnt: 0,
index_buffer: None,
element_cnt: mesh
.vertex_buf()
@@ -185,6 +151,113 @@ impl GraphicsMesh
Ok(())
}
+ pub fn update_vertex_attrs_for_shader(
+ &mut self,
+ curr_gl_ctx: &GlCurrentContextWithFns,
+ shader_vertex_desc: &ShaderVertexDescription,
+ ) -> Result<(), VertexAttrsUpdatingError>
+ {
+ let vertex_field_desc_cnt = u32::try_from(shader_vertex_desc.fields.len())
+ .expect("Shader has too many vertex fields. Count does not fit into u32");
+
+ if self.last_used_vertex_attr_cnt > vertex_field_desc_cnt {
+ for index in vertex_field_desc_cnt..self.last_used_vertex_attr_cnt {
+ self.vertex_arr.disable_attrib(curr_gl_ctx, index);
+ }
+ }
+
+ let mut used_vertex_attr_cnt = 0u32;
+
+ let mut last_attr_index: Option<u32> = None;
+
+ for vertex_attr_props in &self.vertex_attr_props {
+ let Some(vertex_field_desc) =
+ shader_vertex_desc.fields.iter().find(|vertex_field_desc| {
+ *vertex_field_desc.name == vertex_attr_props.name
+ })
+ else {
+ continue;
+ };
+
+ let attrib_index: u32 =
+ vertex_field_desc.varying_input_offset.try_into().unwrap();
+
+ if let Some(last_attr_index) = last_attr_index {
+ if last_attr_index.wrapping_add(1) != attrib_index {
+ cold_path();
+ return Err(
+ VertexAttrsUpdatingError::VertexAttrIndicesNotConsecutive,
+ );
+ }
+ } else if attrib_index != 0 {
+ cold_path();
+ return Err(VertexAttrsUpdatingError::FirstVertexAttrIndexNotZero {
+ vertex_attr_name: vertex_attr_props.name.to_string().into_boxed_str(),
+ unexpected_index: attrib_index,
+ });
+ }
+
+ last_attr_index = Some(attrib_index);
+
+ self.vertex_arr.enable_attrib(curr_gl_ctx, attrib_index);
+
+ self.vertex_arr.set_attrib_format(
+ curr_gl_ctx,
+ attrib_index,
+ match &vertex_attr_props.ty {
+ VertexAttrType::Float32 => GlVertexArrayAttributeFormat {
+ data_type: GlVertexArrayDataType::Float,
+ count: 1,
+ normalized: false,
+ offset: vertex_attr_props.byte_offset.try_into().unwrap(),
+ },
+ VertexAttrType::Float32Array { length } => {
+ GlVertexArrayAttributeFormat {
+ data_type: GlVertexArrayDataType::Float,
+ count: (*length).try_into().unwrap(),
+ normalized: false,
+ offset: vertex_attr_props.byte_offset.try_into().unwrap(),
+ }
+ }
+ },
+ );
+
+ self.vertex_arr.set_attrib_vertex_buf_binding(
+ curr_gl_ctx,
+ attrib_index,
+ VERTEX_BUF_BINDING_INDEX,
+ );
+
+ used_vertex_attr_cnt += 1;
+ }
+
+ self.last_used_vertex_attr_cnt = used_vertex_attr_cnt;
+
+ if used_vertex_attr_cnt as usize != shader_vertex_desc.fields.len() {
+ cold_path();
+
+ return Err(VertexAttrsUpdatingError::MissingVertexAttrs(
+ shader_vertex_desc
+ .fields
+ .iter()
+ .filter_map(|vertex_field_desc| {
+ if self
+ .vertex_attr_props
+ .iter()
+ .any(|prop| prop.name == *vertex_field_desc.name)
+ {
+ return None;
+ }
+
+ Some(vertex_field_desc.name.clone())
+ })
+ .collect(),
+ ));
+ }
+
+ Ok(())
+ }
+
pub fn destroy(&mut self, curr_gl_ctx: &GlCurrentContextWithFns)
{
self.vertex_arr.delete(curr_gl_ctx);
@@ -206,6 +279,26 @@ pub enum Error
StoreIndicesFailed(#[source] opengl_bindings::buffer::Error),
}
+#[derive(Debug, thiserror::Error)]
+pub enum VertexAttrsUpdatingError
+{
+ #[error("Mesh is missing vertex attribute(s) required by shader: {0:?}")]
+ MissingVertexAttrs(Vec<Box<str>>),
+
+ #[error("Shader's vertex attribute indices are not consecutive")]
+ VertexAttrIndicesNotConsecutive,
+
+ #[error(
+ "Shader's first vertex attribute ({vertex_attr_name}) index is not 0, is {}",
+ unexpected_index
+ )]
+ FirstVertexAttrIndexNotZero
+ {
+ vertex_attr_name: Box<str>,
+ unexpected_index: u32,
+ },
+}
+
fn mesh_usage_to_gl_buffer_usage(mesh_usage: MeshUsage) -> GlBufferUsage
{
match mesh_usage {
diff --git a/engine/src/rendering/shader.rs b/engine/src/rendering/shader.rs
index b508670..3bcf73e 100644
--- a/engine/src/rendering/shader.rs
+++ b/engine/src/rendering/shader.rs
@@ -4,6 +4,7 @@ use std::collections::HashMap;
use std::fmt::Debug;
use std::path::Path;
use std::str::Utf8Error;
+use std::sync::Arc;
use bitflags::{bitflags, bitflags_match};
use ecs::phase::INIT as INIT_PHASE;
@@ -156,15 +157,24 @@ impl<'a> EntryPointReflection<'a>
pub struct Program
{
inner: SlangComponentType,
+ metadata: ProgramMetadata,
}
impl Program
{
- pub fn link(&self) -> Result<Program, Error>
+ pub fn into_linked(self) -> Result<Program, Error>
{
let linked_program = self.inner.link()?;
- Ok(Program { inner: linked_program })
+ Ok(Program {
+ inner: linked_program,
+ metadata: self.metadata,
+ })
+ }
+
+ pub fn metadata(&self) -> &ProgramMetadata
+ {
+ &self.metadata
}
pub fn get_entry_point_code(&self, entry_point_index: u32) -> Result<Blob, Error>
@@ -791,7 +801,7 @@ pub struct Context
_global_session: SlangGlobalSession,
session: SlangSession,
modules: HashMap<AssetId, Module>,
- programs: HashMap<AssetId, (Program, ProgramMetadata)>,
+ programs: HashMap<AssetId, Program>,
}
impl Context
@@ -803,38 +813,70 @@ impl Context
pub fn get_program(&self, asset_id: &AssetId) -> Option<&Program>
{
- self.programs.get(asset_id).map(|(program, _)| program)
- }
-
- pub fn get_program_metadata(&self, asset_id: &AssetId) -> Option<&ProgramMetadata>
- {
- self.programs
- .get(asset_id)
- .map(|(_, program_metadata)| program_metadata)
+ self.programs.get(asset_id)
}
pub fn compose_into_program(
&self,
- modules: impl IntoIterator<Item = Module>,
- entry_points: impl IntoIterator<Item = EntryPoint>,
- ) -> Result<Program, Error>
+ module: Module,
+ link_entrypoints: EntrypointFlags,
+ ) -> Result<Program, ComposeProgramError>
{
- let components =
- modules
- .into_iter()
- .map(|module| SlangComponentType::from(module.inner.clone()))
- .chain(entry_points.into_iter().map(|entry_point| {
- SlangComponentType::from(entry_point.inner.clone())
- }))
- .collect::<Vec<_>>();
-
- let program = self.session.create_composite_component_type(&components)?;
-
- Ok(Program { inner: program })
+ let entry_points = link_entrypoints
+ .iter()
+ .filter_map(|entrypoint_flag| {
+ let entrypoint_name = bitflags_match!(entrypoint_flag, {
+ EntrypointFlags::VERTEX => Some("vertex_main"),
+ EntrypointFlags::FRAGMENT => Some("fragment_main"),
+ _ => None
+ })?;
+
+ let Some(entry_point) = module.get_entry_point(entrypoint_name) else {
+ return Some(Err(ComposeProgramError::EntrypointNotFoundError {
+ entrypoint_name,
+ }));
+ };
+
+ Some(Ok(entry_point))
+ })
+ .collect::<Result<Vec<_>, _>>()?;
+
+ let components = entry_points
+ .into_iter()
+ .map(|entry_point| SlangComponentType::from(entry_point.inner))
+ .chain([SlangComponentType::from(module.inner)])
+ .collect::<Vec<_>>();
+
+ let program = self
+ .session
+ .create_composite_component_type(&components)
+ .map_err(|err| ComposeProgramError::Other(Error(err)))?;
+
+ let vertex_desc = if link_entrypoints.contains(EntrypointFlags::VERTEX) {
+ // TODO: Do not have hard coded target here
+ let Ok(program_reflection) = program.layout(0) else {
+ unreachable!();
+ };
+
+ let program_reflection = ProgramReflection { inner: program_reflection };
+
+ Some(VertexDescription::new(
+ &program_reflection
+ .get_entry_point_by_name("vertex_main")
+ .expect("Not possible"),
+ )?)
+ } else {
+ None
+ };
+
+ Ok(Program {
+ inner: program,
+ metadata: ProgramMetadata { vertex_desc },
+ })
}
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct ProgramMetadata
{
@@ -843,11 +885,11 @@ pub struct ProgramMetadata
pub vertex_desc: Option<VertexDescription>,
}
-#[derive(Debug)]
+#[derive(Debug, Clone)]
#[non_exhaustive]
pub struct VertexDescription
{
- pub fields: Box<[VertexFieldDescription]>,
+ pub fields: Arc<[VertexFieldDescription]>,
}
impl VertexDescription
@@ -916,7 +958,7 @@ impl VertexDescription
})
.collect::<Result<Vec<_>, _>>()?;
- Ok(Self { fields: fields.into_boxed_slice() })
+ Ok(Self { fields: fields.into() })
}
}
@@ -955,6 +997,22 @@ pub enum VertexDescriptionError
}
#[derive(Debug, thiserror::Error)]
+pub enum ComposeProgramError
+{
+ #[error("Shader module does not have a '{entrypoint_name}' entry point")]
+ EntrypointNotFoundError
+ {
+ entrypoint_name: &'static str
+ },
+
+ #[error("Failed to create vertex description")]
+ VertexDescriptionCreationFailed(#[from] VertexDescriptionError),
+
+ #[error(transparent)]
+ Other(Error),
+}
+
+#[derive(Debug, thiserror::Error)]
#[error(transparent)]
pub struct Error(#[from] shader_slang::Error);
@@ -1108,44 +1166,17 @@ fn load_modules(
if !module_source.link_entrypoints.is_empty() {
assert!(context.programs.get(asset_id).is_none());
- let entry_points = match module_source
- .link_entrypoints
- .iter()
- .filter_map(|entrypoint_flag| {
- let entrypoint_name = bitflags_match!(entrypoint_flag, {
- EntrypointFlags::VERTEX => Some("vertex_main"),
- EntrypointFlags::FRAGMENT => Some("fragment_main"),
- _ => None
- })?;
-
- let Some(entry_point) = module.get_entry_point(entrypoint_name)
- else {
- return Some(Err(EntrypointNotFoundError { entrypoint_name }));
- };
-
- Some(Ok(entry_point))
- })
- .collect::<Result<Vec<_>, EntrypointNotFoundError>>()
+ let shader_program = match context
+ .compose_into_program(module, module_source.link_entrypoints)
{
- Ok(entry_points) => entry_points,
- Err(EntrypointNotFoundError { entrypoint_name }) => {
- tracing::error!(
- "Shader module does not have a '{entrypoint_name}' entry point"
- );
+ Ok(shader_program) => shader_program,
+ Err(err) => {
+ tracing::error!("Failed to compose shader into program: {err}");
continue;
}
};
- let shader_program =
- match context.compose_into_program([module], entry_points) {
- Ok(shader_program) => shader_program,
- Err(err) => {
- tracing::error!("Failed to compose shader into program: {err}");
- continue;
- }
- };
-
- let linked_shader_program = match shader_program.link() {
+ let linked_shader_program = match shader_program.into_linked() {
Ok(linked_shader_program) => linked_shader_program,
Err(err) => {
tracing::error!("Failed to link shader: {err}");
@@ -1153,33 +1184,7 @@ fn load_modules(
}
};
- let vertex_desc = if module_source
- .link_entrypoints
- .contains(EntrypointFlags::VERTEX)
- {
- VertexDescription::new(
- &shader_program
- .reflection(0)
- .expect("Not possible")
- .get_entry_point_by_name("vertex_main")
- .expect("Not possible"),
- )
- .inspect_err(|err| {
- tracing::error!(
- "Failed to create a vertex description for shader {}: {}",
- asset_label,
- err
- );
- })
- .ok()
- } else {
- None
- };
-
- context.programs.insert(
- *asset_id,
- (linked_shader_program, ProgramMetadata { vertex_desc }),
- );
+ context.programs.insert(*asset_id, linked_shader_program);
}
}
@@ -1199,9 +1204,3 @@ fn load_module(
Ok(Module { inner: module })
}
-
-#[derive(Debug)]
-struct EntrypointNotFoundError
-{
- entrypoint_name: &'static str,
-}