diff options
| -rw-r--r-- | Cargo.lock | 9 | ||||
| -rw-r--r-- | engine/Cargo.toml | 1 | ||||
| -rw-r--r-- | engine/src/rendering/shader/cursor.rs | 103 |
3 files changed, 99 insertions, 14 deletions
@@ -327,6 +327,12 @@ dependencies = [ ] [[package]] +name = "circular-buffer" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f5610398bbf405be68c4daeadee379d4dca31226cdf9076746a875bc58a69e3" + +[[package]] name = "clang-sys" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -574,6 +580,7 @@ version = "0.1.0" dependencies = [ "bitflags 2.11.1", "build-rs", + "circular-buffer", "crossbeam-queue", "dear-imgui-rs", "engine-ecs", @@ -1103,7 +1110,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc2f4eb4bc735547cfed7c0a4922cbd04a4655978c09b54f1f7b228750664c34" dependencies = [ "cfg-if", - "windows-targets 0.48.5", + "windows-targets 0.52.6", ] [[package]] diff --git a/engine/Cargo.toml b/engine/Cargo.toml index fa30dd0..df29fd3 100644 --- a/engine/Cargo.toml +++ b/engine/Cargo.toml @@ -14,6 +14,7 @@ paste = "1.0.14" safer-ffi = "0.1.13" crossbeam-queue = "0.3.12" parking_lot = "0.12.3" +circular-buffer = "2.0.0" engine-macros = { workspace = true } engine-ecs = { workspace = true } engine-reflection = { workspace = true } diff --git a/engine/src/rendering/shader/cursor.rs b/engine/src/rendering/shader/cursor.rs index 32dee00..ba8bed7 100644 --- a/engine/src/rendering/shader/cursor.rs +++ b/engine/src/rendering/shader/cursor.rs @@ -1,5 +1,9 @@ +use std::borrow::Cow; +use std::fmt::Display; use std::hint::cold_path; +use circular_buffer::FixedCircularBuffer; + use crate::color::Color; use crate::data_types::matrix::Matrix; use crate::data_types::vector::Vec3; @@ -18,6 +22,7 @@ pub struct Cursor<'a> { type_layout: TypeLayout<'a>, binding_location: BindingLocation, + location_path: LocationPath, } impl<'a> Cursor<'a> @@ -33,12 +38,16 @@ impl<'a> Cursor<'a> Self { type_layout: var_layout.type_layout().unwrap(), binding_location, + location_path: LocationPath::default(), } } - pub fn field(&self, name: &str) -> Self + pub fn field(&self, name: impl Into<Cow<'static, str>>) -> Self { - let Some(field_var_layout) = self.type_layout.get_field_by_name(name) else { + let name = name.into(); + + let Some(field_var_layout) = self.type_layout.get_field_by_name(name.as_ref()) + else { panic!("Field '{name}' does not exist"); }; @@ -59,6 +68,10 @@ impl<'a> Cursor<'a> type_kind => unimplemented!("Type kind {type_kind:?} is not yet supported"), }; + let mut location_path = self.location_path.clone(); + + location_path.push(Location::Field(name)); + Self { type_layout: field_var_layout.type_layout().unwrap(), binding_location: BindingLocation { @@ -76,6 +89,7 @@ impl<'a> Cursor<'a> byte_offset: self.binding_location.byte_offset + field_var_layout.offset(), }, + location_path, } } @@ -87,19 +101,14 @@ impl<'a> Cursor<'a> self.type_layout = element_type_layout; - self - } - - pub fn with_field(self, name: &str, func: impl FnOnce(Self) -> Self) -> Self - { - let _ = func(self.field(name)); + self.location_path.push(Location::Element(index)); self } pub fn binding(self, value: BindingValue) -> Result<Binding, BindingError> { - value.validate_for_shader_type(self.type_layout)?; + value.validate_for_shader_type(self.type_layout, self.location_path)?; Ok(Binding { location: self.binding_location, @@ -113,6 +122,66 @@ impl<'a> Cursor<'a> } } +/// Shader cursor location. +#[derive(Debug, Clone, Default)] +pub struct LocationPath +{ + locations: FixedCircularBuffer<Location, 16>, + is_truncated: bool, +} + +impl LocationPath +{ + fn push(&mut self, location: Location) + { + if self.locations.push_back(location).is_some() { + self.is_truncated = true; + } + } +} + +impl Display for LocationPath +{ + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + if self.is_truncated { + write!(formatter, "(...)")?; + } + + for location in &self.locations { + match location { + Location::Field(field) => { + write!(formatter, ".{field}")?; + } + Location::Element(element) => { + write!(formatter, "[{element}]")?; + } + } + } + + Ok(()) + } +} + +/// Shader cursor location. +#[derive(Debug, Clone)] +pub enum Location +{ + Field(Cow<'static, str>), + Element(usize), +} + +impl Display for Location +{ + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result + { + match self { + Self::Field(field) => <Cow<'static, str> as Display>::fmt(field, formatter), + Self::Element(element) => <usize as Display>::fmt(element, formatter), + } + } +} + #[derive(Debug, Clone)] pub struct BindingLocation { @@ -135,7 +204,11 @@ pub enum BindingValue impl BindingValue { - fn validate_for_shader_type(&self, ty: TypeLayout<'_>) -> Result<(), BindingError> + fn validate_for_shader_type( + &self, + ty: TypeLayout<'_>, + location_path: LocationPath, + ) -> Result<(), BindingError> { match ( self, @@ -205,7 +278,10 @@ impl BindingValue } _ => { cold_path(); - Err(BindingError::IncorrectValueType { value: self.clone() }) + Err(BindingError::IncorrectValueType { + value: self.clone(), + location_path, + }) } } } @@ -271,9 +347,10 @@ pub struct Binding #[non_exhaustive] pub enum BindingError { - #[error("Value {value:?} has incorrect type for shader binding location")] + #[error("Value {value:?} has incorrect type for value at {location_path} in shader")] IncorrectValueType { - value: BindingValue + value: BindingValue, + location_path: LocationPath, }, } |
