diff options
Diffstat (limited to 'engine/src/rendering/shader.rs')
| -rw-r--r-- | engine/src/rendering/shader.rs | 120 |
1 files changed, 110 insertions, 10 deletions
diff --git a/engine/src/rendering/shader.rs b/engine/src/rendering/shader.rs index 3142400..6f50a79 100644 --- a/engine/src/rendering/shader.rs +++ b/engine/src/rendering/shader.rs @@ -1,7 +1,7 @@ use std::any::type_name; use std::borrow::Cow; -use std::collections::HashMap; -use std::fmt::Debug; +use std::collections::{HashMap, HashSet}; +use std::fmt::{Debug, Display, Write}; use std::path::Path; use std::str::Utf8Error; use std::sync::Arc; @@ -34,10 +34,16 @@ use crate::ecs::pair::ChildOf; use crate::ecs::phase::{Phase, POST_UPDATE as POST_UPDATE_PHASE}; use crate::ecs::sole::Single; use crate::ecs::{declare_entity, pair, Component, Sole}; +use crate::mesh::vertex_buffer::VertexLabel; pub mod cursor; pub mod default; +pub const STD_VERTEX_INPUT_SEMANTIC_NAME_POSITION: &str = "STD_POSITION"; +pub const STD_VERTEX_INPUT_SEMANTIC_NAME_NORMAL: &str = "STD_NORMAL"; +pub const STD_VERTEX_INPUT_SEMANTIC_NAME_UV: &str = "STD_UV"; +pub const STD_VERTEX_INPUT_SEMANTIC_NAME_COLOR: &str = "STD_COLOR"; + #[derive(Debug, Clone, Component)] pub struct Shader { @@ -983,15 +989,31 @@ impl VertexDescription ); }); + let mut seen_inputs = HashSet::<VertexInputSemName>::new(); + Ok(Self { inputs: inputs .filter(|var_input| var_input.type_layout.kind() != TypeKind::Struct) .map(|var_input| { - let name = var_input - .var_layout - .name() - .unwrap_or("<unnamed>") - .to_string(); + let name = var_input.var_layout.name().unwrap_or("<unnamed>"); + + let semantic_name = + var_input.var_layout.semantic_name().ok_or_else(|| { + VertexDescriptionError::VertexInputMissingSemanticName { + name: name.to_owned(), + } + })?; + + let semantic_name = + VertexInputSemName::from_semantic_name(semantic_name); + + if seen_inputs.contains(&semantic_name) { + return Err( + VertexDescriptionError::VertexInputHasOccupiedSemanticName { + name: name.to_owned(), + }, + ); + } let scalar_type = match ( var_input.type_layout.kind(), @@ -1002,14 +1024,16 @@ impl VertexDescription _ => { return Err( VertexDescriptionError::UnsupportedVertexInputType { - name, + name: name.to_owned(), }, ); } }; + seen_inputs.insert(semantic_name.clone()); + Ok(VertexInputDescription { - name: name.into_boxed_str(), + semantic_name, index: var_input.index, type_kind: var_input.type_layout.kind(), scalar_type, @@ -1022,14 +1046,76 @@ impl VertexDescription } #[derive(Debug)] +#[non_exhaustive] pub struct VertexInputDescription { - pub name: Box<str>, + pub semantic_name: VertexInputSemName, pub index: usize, pub type_kind: TypeKind, pub scalar_type: ScalarType, } +#[derive(Debug, Clone, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum VertexInputSemName +{ + Position, + Normal, + Uv, + Color, + Other(Box<str>), +} + +impl VertexInputSemName +{ + fn from_semantic_name(semantic_name: &str) -> Self + { + match semantic_name { + STD_VERTEX_INPUT_SEMANTIC_NAME_POSITION => Self::Position, + STD_VERTEX_INPUT_SEMANTIC_NAME_NORMAL => Self::Normal, + STD_VERTEX_INPUT_SEMANTIC_NAME_UV => Self::Uv, + STD_VERTEX_INPUT_SEMANTIC_NAME_COLOR => Self::Color, + _ => Self::Other(semantic_name.to_lowercase().into_boxed_str()), + } + } + + pub fn matches_vertex_label(&self, vertex_label: &VertexLabel) -> bool + { + match (self, vertex_label) { + (Self::Position, VertexLabel::Position) + | (Self::Normal, VertexLabel::Normal) + | (Self::Uv, VertexLabel::Uv) + | (Self::Color, VertexLabel::Color) => true, + (Self::Other(other), VertexLabel::Other(other_vertex_label)) => { + **other == *other_vertex_label + } + _ => false, + } + } +} + +impl Display for VertexInputSemName +{ + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + match self { + Self::Position => { + formatter.write_str(STD_VERTEX_INPUT_SEMANTIC_NAME_POSITION) + } + Self::Normal => formatter.write_str(STD_VERTEX_INPUT_SEMANTIC_NAME_NORMAL), + Self::Uv => formatter.write_str(STD_VERTEX_INPUT_SEMANTIC_NAME_UV), + Self::Color => formatter.write_str(STD_VERTEX_INPUT_SEMANTIC_NAME_COLOR), + Self::Other(other) => { + for character in other.chars() { + formatter.write_char(character.to_ascii_uppercase())?; + } + + Ok(()) + } + } + } +} + #[derive(Debug, thiserror::Error)] pub enum VertexDescriptionError { @@ -1041,6 +1127,20 @@ pub enum VertexDescriptionError { name: String }, + + #[error("Vertex input '{name}' is missing a semantic name")] + VertexInputMissingSemanticName + { + name: String + }, + + #[error( + "Vertex input '{name}' has a semantic name already used by another vertex input" + )] + VertexInputHasOccupiedSemanticName + { + name: String + }, } #[derive(Debug, thiserror::Error)] |
