summaryrefslogtreecommitdiff
path: root/engine/src/rendering
diff options
context:
space:
mode:
Diffstat (limited to 'engine/src/rendering')
-rw-r--r--engine/src/rendering/shader/cursor.rs103
1 files changed, 90 insertions, 13 deletions
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,
},
}