diff options
| author | HampusM <hampus@hampusmat.com> | 2026-03-20 14:22:19 +0100 |
|---|---|---|
| committer | HampusM <hampus@hampusmat.com> | 2026-03-20 14:22:19 +0100 |
| commit | f285f82072b491b1f3cc92db8e08485f26779d5a (patch) | |
| tree | bf6c6c61cdfb3a12550e55966c8552957ade9e71 /engine/src/shader/cursor.rs | |
| parent | 0546d575c11d3668d0f95933697ae4f670fe2a55 (diff) | |
Diffstat (limited to 'engine/src/shader/cursor.rs')
| -rw-r--r-- | engine/src/shader/cursor.rs | 160 |
1 files changed, 160 insertions, 0 deletions
diff --git a/engine/src/shader/cursor.rs b/engine/src/shader/cursor.rs new file mode 100644 index 0000000..b5ba4e0 --- /dev/null +++ b/engine/src/shader/cursor.rs @@ -0,0 +1,160 @@ +use crate::asset::Handle as AssetHandle; +use crate::image::Image; +use crate::matrix::Matrix; +use crate::shader::{TypeKind, TypeLayout, VariableLayout}; +use crate::vector::Vec3; + +/// Shader cursor +#[derive(Clone)] +pub struct Cursor<'a> +{ + type_layout: TypeLayout<'a>, + binding_location: BindingLocation, +} + +impl<'a> Cursor<'a> +{ + pub fn new(var_layout: VariableLayout<'a>) -> Self + { + let binding_location = BindingLocation { + binding_index: var_layout.binding_index(), + binding_size: 0, + byte_offset: var_layout.offset(), + }; + + Self { + type_layout: var_layout.type_layout().unwrap(), + binding_location, + } + } + + pub fn field(&self, name: &str) -> Self + { + let Some(field_var_layout) = self.type_layout.get_field_by_name(name) else { + panic!("Field '{name}' does not exist"); + }; + + let field_type_kind = field_var_layout.ty().unwrap().kind(); + + let field_var_layout = match field_type_kind { + TypeKind::ConstantBuffer => field_var_layout + .type_layout() + .expect("Constant buffer field has no type layout") + .element_var_layout() + .expect("Constant buffer field type layout has no element var layout"), + TypeKind::Array + | TypeKind::Matrix + | TypeKind::Scalar + | TypeKind::Vector + | TypeKind::Struct + | TypeKind::Resource => field_var_layout, + type_kind => unimplemented!("Type kind {type_kind:?} is not yet supported"), + }; + + Self { + type_layout: field_var_layout.type_layout().unwrap(), + binding_location: BindingLocation { + binding_index: self.binding_location.binding_index + + field_var_layout.binding_index(), + binding_size: if field_type_kind == TypeKind::ConstantBuffer { + field_var_layout + .type_layout() + .unwrap() + .uniform_size() + .unwrap() + } else { + self.binding_location.binding_size + }, + byte_offset: self.binding_location.byte_offset + + field_var_layout.offset(), + }, + } + } + + pub fn element(mut self, index: usize) -> Self + { + let element_type_layout = self.type_layout.element_type_layout().unwrap(); + + self.binding_location.byte_offset += index * element_type_layout.stride(); + + 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 + } + + pub fn binding_location(&self) -> &BindingLocation + { + &self.binding_location + } + + pub fn into_binding_location(self) -> BindingLocation + { + self.binding_location + } +} + +#[derive(Debug, Clone)] +pub struct BindingLocation +{ + pub binding_index: u32, + pub binding_size: usize, + pub byte_offset: usize, +} + +#[derive(Debug, Clone)] +pub enum BindingValue +{ + Uint(u32), + Int(i32), + Float(f32), + FVec3(Vec3<f32>), + FMat4x4(Matrix<f32, 4, 4>), + Texture(AssetHandle<Image>), +} + +impl From<u32> for BindingValue +{ + fn from(value: u32) -> Self + { + BindingValue::Uint(value) + } +} + +impl From<i32> for BindingValue +{ + fn from(value: i32) -> Self + { + BindingValue::Int(value) + } +} + +impl From<f32> for BindingValue +{ + fn from(value: f32) -> Self + { + BindingValue::Float(value) + } +} + +impl From<Vec3<f32>> for BindingValue +{ + fn from(vec: Vec3<f32>) -> Self + { + BindingValue::FVec3(vec) + } +} + +impl From<Matrix<f32, 4, 4>> for BindingValue +{ + fn from(matrix: Matrix<f32, 4, 4>) -> Self + { + BindingValue::FMat4x4(matrix) + } +} |
