diff options
Diffstat (limited to 'engine/src')
| -rw-r--r-- | engine/src/rendering.rs | 22 | ||||
| -rw-r--r-- | engine/src/rendering/main_render_pass.rs | 16 | ||||
| -rw-r--r-- | engine/src/rendering/shader.rs | 52 | ||||
| -rw-r--r-- | engine/src/rendering/shader/cursor.rs | 116 | ||||
| -rw-r--r-- | engine/src/rendering/shader/default.rs | 305 | ||||
| -rw-r--r-- | engine/src/windowing.rs | 9 |
6 files changed, 338 insertions, 182 deletions
diff --git a/engine/src/rendering.rs b/engine/src/rendering.rs index 87c3b6f..4871f08 100644 --- a/engine/src/rendering.rs +++ b/engine/src/rendering.rs @@ -24,9 +24,9 @@ use crate::mesh::Mesh; use crate::rendering::blending::Config as BlendingConfig; use crate::rendering::object::{Id as ObjectId, Store as ObjectStore}; use crate::rendering::shader::cursor::{ + Binding as ShaderBinding, BindingLocation as ShaderBindingLocation, BindingValue as ShaderBindingValue, - Cursor as ShaderCursor, }; use crate::rendering::shader::Program as ShaderProgram; use crate::texture::Texture; @@ -548,24 +548,8 @@ fn handle_window_removed( #[derive(Default, Clone, Component)] pub struct PendingShaderBindings { - pub bindings: Vec<(ShaderBindingLocation, ShaderBindingValue)>, - pub surface_specific_bindings: - Vec<(SurfaceId, ShaderBindingLocation, ShaderBindingValue)>, -} - -impl<'a> Extend<(ShaderCursor<'a>, ShaderBindingValue)> for PendingShaderBindings -{ - fn extend<Iter: IntoIterator<Item = (ShaderCursor<'a>, ShaderBindingValue)>>( - &mut self, - iter: Iter, - ) - { - self.bindings.extend(iter.into_iter().map( - |(shader_cursor, shader_binding_val)| { - (shader_cursor.into_binding_location(), shader_binding_val) - }, - )) - } + pub bindings: Vec<ShaderBinding>, + pub surface_specific_bindings: Vec<(SurfaceId, ShaderBinding)>, } #[derive(Debug, Default, Clone, Component)] diff --git a/engine/src/rendering/main_render_pass.rs b/engine/src/rendering/main_render_pass.rs index 7d06bf2..d83fad4 100644 --- a/engine/src/rendering/main_render_pass.rs +++ b/engine/src/rendering/main_render_pass.rs @@ -6,6 +6,7 @@ use crate::ecs::Query; use crate::error; use crate::model::{MaterialSearchResult, Model}; use crate::rendering::object::{Id as ObjectId, Store as ObjectStore}; +use crate::rendering::shader::cursor::Binding as ShaderBinding; use crate::rendering::shader::default::ASSET_LABEL as DEFAULT_SHADER_ASSET_LABEL; use crate::rendering::shader::{ Context as ShaderContext, @@ -177,8 +178,10 @@ pub fn add_main_render_passes( } } - for (shader_binding_loc, shader_binding_val) in - &pending_shader_bindings.bindings + for ShaderBinding { + location: shader_binding_loc, + value: shader_binding_val, + } in &pending_shader_bindings.bindings { render_pass.commands.push(Command::SetShaderBinding( shader_binding_loc.clone(), @@ -186,8 +189,13 @@ pub fn add_main_render_passes( )); } - for (shader_binding_surface_id, shader_binding_loc, shader_binding_val) in - &pending_shader_bindings.surface_specific_bindings + for ( + shader_binding_surface_id, + ShaderBinding { + location: shader_binding_loc, + value: shader_binding_val, + }, + ) in &pending_shader_bindings.surface_specific_bindings { if *shader_binding_surface_id != surface_spec.id { continue; diff --git a/engine/src/rendering/shader.rs b/engine/src/rendering/shader.rs index 6b68e1e..74109a7 100644 --- a/engine/src/rendering/shader.rs +++ b/engine/src/rendering/shader.rs @@ -340,6 +340,13 @@ impl<'a> TypeLayout<'a> )) } + pub fn resource_shape(&self) -> Option<ResourceShape> + { + Some(ResourceShape::from_bits_retain( + self.inner.resource_shape()? as u32, + )) + } + pub fn get_field_by_name(&self, name: &str) -> Option<VariableLayout<'a>> { let index = self.inner.find_field_index_by_name(name); @@ -400,6 +407,21 @@ impl<'a> TypeLayout<'a> self.inner.field_count() } + pub fn element_cnt(&self) -> Option<usize> + { + self.inner.element_count() + } + + pub fn row_cnt(&self) -> Option<u32> + { + self.inner.row_count() + } + + pub fn column_cnt(&self) -> Option<u32> + { + self.inner.column_count() + } + pub fn element_type_layout(&self) -> Option<TypeLayout<'a>> { self.inner @@ -582,6 +604,36 @@ impl ScalarType } } +bitflags! { +#[derive(Debug, Copy, Clone)] +pub struct ResourceShape: u32 { + const BASE = shader_slang::ResourceShape::SlangResourceBaseShapeMask as u32; + const NONE = shader_slang::ResourceShape::SlangResourceNone as u32; + const TEXTURE_1D = shader_slang::ResourceShape::SlangTexture1d as u32; + const TEXTURE_2D = shader_slang::ResourceShape::SlangTexture2d as u32; + const TEXTURE_3D = shader_slang::ResourceShape::SlangTexture3d as u32; + const TEXTURE_CUBE = shader_slang::ResourceShape::SlangTextureCube as u32; + const TEXTURE_BUFFER = shader_slang::ResourceShape::SlangTextureBuffer as u32; + const STRUCTURED_BUFFER = shader_slang::ResourceShape::SlangStructuredBuffer as u32; + const BYTE_ADDRESS_BUFFER = shader_slang::ResourceShape::SlangByteAddressBuffer as u32; + const UNKNOWN = shader_slang::ResourceShape::SlangResourceUnknown as u32; + const ACCELERATION_STRUCTURE = shader_slang::ResourceShape::SlangAccelerationStructure as u32; + const TEXTURE_SUBPASS = shader_slang::ResourceShape::SlangTextureSubpass as u32; + const EXT_SHAPE = shader_slang::ResourceShape::SlangResourceExtShapeMask as u32; + const TEXTURE_FEEDBACK_FLAG = shader_slang::ResourceShape::SlangTextureFeedbackFlag as u32; + const TEXTURE_SHADOW_FLAG = shader_slang::ResourceShape::SlangTextureShadowFlag as u32; + const TEXTURE_ARRAY_FLAG = shader_slang::ResourceShape::SlangTextureArrayFlag as u32; + const TEXTURE_MULTISAMPLE_FLAG = shader_slang::ResourceShape::SlangTextureMultisampleFlag as u32; + const TEXTURE_COMBINED_FLAG = shader_slang::ResourceShape::SlangTextureCombinedFlag as u32; + const TEXTURE_1D_ARRAY = shader_slang::ResourceShape::SlangTexture1dArray as u32; + const TEXTURE_2D_ARRAY = shader_slang::ResourceShape::SlangTexture2dArray as u32; + const TEXTURE_CUBE_ARRAY = shader_slang::ResourceShape::SlangTextureCubeArray as u32; + const TEXTURE_2D_MULTISAMPLE = shader_slang::ResourceShape::SlangTexture2dMultisample as u32; + const TEXTURE_2D_MULTISAMPLE_ARRAY = shader_slang::ResourceShape::SlangTexture2dMultisampleArray as u32; + const TEXTURE_SUBPASS_MULTISAMPLE = shader_slang::ResourceShape::SlangTextureSubpassMultisample as u32; +} +} + #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] pub enum ParameterCategory { diff --git a/engine/src/rendering/shader/cursor.rs b/engine/src/rendering/shader/cursor.rs index 8aab4f2..32dee00 100644 --- a/engine/src/rendering/shader/cursor.rs +++ b/engine/src/rendering/shader/cursor.rs @@ -1,8 +1,16 @@ +use std::hint::cold_path; + use crate::color::Color; use crate::data_types::matrix::Matrix; use crate::data_types::vector::Vec3; use crate::rendering::object::Id as RenderingObjectId; -use crate::rendering::shader::{TypeKind, TypeLayout, VariableLayout}; +use crate::rendering::shader::{ + ResourceShape, + ScalarType, + TypeKind, + TypeLayout, + VariableLayout, +}; /// Shader cursor #[derive(Clone)] @@ -89,9 +97,14 @@ impl<'a> Cursor<'a> self } - pub fn binding_location(&self) -> &BindingLocation + pub fn binding(self, value: BindingValue) -> Result<Binding, BindingError> { - &self.binding_location + value.validate_for_shader_type(self.type_layout)?; + + Ok(Binding { + location: self.binding_location, + value, + }) } pub fn into_binding_location(self) -> BindingLocation @@ -120,6 +133,84 @@ pub enum BindingValue Texture(RenderingObjectId), } +impl BindingValue +{ + fn validate_for_shader_type(&self, ty: TypeLayout<'_>) -> Result<(), BindingError> + { + match ( + self, + ty.kind(), + ty.scalar_type(), + ty.element_type_layout() + .map(|elem_ty| elem_ty.scalar_type()), + ty.element_cnt(), + ty.resource_shape(), + ) { + (Self::Uint(_), TypeKind::Scalar, Some(ScalarType::Uint32), _, _, _) + | (Self::Int(_), TypeKind::Scalar, Some(ScalarType::Int32), _, _, _) + | (Self::Float(_), TypeKind::Scalar, Some(ScalarType::Float32), _, _, _) + | ( + Self::FVec3(_), + TypeKind::Vector, + _, + Some(Some(ScalarType::Float32)), + Some(3), + _, + ) + | ( + Self::Color(Color::Rgb(_)), + TypeKind::Vector, + _, + Some(Some(ScalarType::Float32)), + Some(3), + _, + ) + | ( + Self::Color(Color::Rgba(_)), + TypeKind::Vector, + _, + Some(Some(ScalarType::Float32)), + Some(4), + _, + ) + | ( + Self::Color(Color::Luma(_)), + TypeKind::Vector, + _, + Some(Some(ScalarType::Float32)), + Some(1), + _, + ) + | ( + Self::Color(Color::LumaA(_)), + TypeKind::Vector, + _, + Some(Some(ScalarType::Float32)), + Some(2), + _, + ) => Ok(()), + ( + Self::FMat4x4(_), + TypeKind::Matrix, + _, + Some(Some(ScalarType::Float32)), + _, + _, + ) if ty.row_cnt() == Some(4) && ty.column_cnt() == Some(4) => Ok(()), + (Self::Texture(_), TypeKind::Resource, _, _, _, Some(res_shape)) + if (res_shape & ResourceShape::BASE) + .contains(ResourceShape::TEXTURE_2D) => + { + Ok(()) + } + _ => { + cold_path(); + Err(BindingError::IncorrectValueType { value: self.clone() }) + } + } + } +} + impl From<u32> for BindingValue { fn from(value: u32) -> Self @@ -167,3 +258,22 @@ impl From<Matrix<f32, 4, 4>> for BindingValue BindingValue::FMat4x4(matrix) } } + +#[derive(Debug, Clone)] +#[non_exhaustive] +pub struct Binding +{ + pub location: BindingLocation, + pub value: BindingValue, +} + +#[derive(Debug, thiserror::Error)] +#[non_exhaustive] +pub enum BindingError +{ + #[error("Value {value:?} has incorrect type for shader binding location")] + IncorrectValueType + { + value: BindingValue + }, +} diff --git a/engine/src/rendering/shader/default.rs b/engine/src/rendering/shader/default.rs index bb5c366..6621d06 100644 --- a/engine/src/rendering/shader/default.rs +++ b/engine/src/rendering/shader/default.rs @@ -165,22 +165,20 @@ pub fn enqueue_set_shader_bindings( let lighting_shader_cursor = shader_cursor.field("Uniforms").field("lighting"); let material_shader_cursor = lighting_shader_cursor.field("material"); - shader_bindings.extend([ - (model_3d_shader_cursor.field("model"), model_matrix.into()), - ( - model_3d_shader_cursor.field("model_inverted"), - inverted_model_matrix.into(), - ), - ( - model_3d_shader_cursor.field("view"), - create_view_matrix(&camera, camera_world_pos.position).into(), - ), - ( - lighting_shader_cursor.field("view_pos"), - camera_world_pos.position.into(), - ), - ( - material_shader_cursor.field("ambient"), + shader_bindings.bindings.extend([ + model_3d_shader_cursor + .field("model") + .binding(model_matrix.into())?, + model_3d_shader_cursor + .field("model_inverted") + .binding(inverted_model_matrix.into())?, + model_3d_shader_cursor + .field("view") + .binding(create_view_matrix(&camera, camera_world_pos.position).into())?, + lighting_shader_cursor + .field("view_pos") + .binding(camera_world_pos.position.into())?, + material_shader_cursor.field("ambient").binding( (if material_flags.use_ambient_color { &model_material.ambient } else { @@ -188,161 +186,164 @@ pub fn enqueue_set_shader_bindings( } .clone()) .into(), - ), - ( - material_shader_cursor.field("diffuse"), - model_material.diffuse.clone().into(), - ), - ( - material_shader_cursor.field("specular"), - model_material.specular.clone().into(), - ), - ( - material_shader_cursor.field("shininess"), - model_material.shininess.into(), - ), - ( - lighting_shader_cursor.field("directional_light_cnt"), + )?, + material_shader_cursor + .field("diffuse") + .binding(model_material.diffuse.clone().into())?, + material_shader_cursor + .field("specular") + .binding(model_material.specular.clone().into())?, + material_shader_cursor + .field("shininess") + .binding(model_material.shininess.into())?, + lighting_shader_cursor + .field("directional_light_cnt") + .binding( u32::try_from(directional_light_query.iter().count()) .expect( "Directional light count does not fit in 32-bit unsigned integer", ) .into(), - ), - ( - lighting_shader_cursor.field("point_light_cnt"), + )?, + lighting_shader_cursor.field("point_light_cnt").binding( u32::try_from(point_light_query.iter().count()) .expect("Point light count does not fit in 32-bit unsigned integer") .into(), - ), + )?, ]); for (window, window_surface_spec) in &window_query { shader_bindings.surface_specific_bindings.push(( window_surface_spec.id, - model_3d_shader_cursor - .field("projection") - .into_binding_location(), - create_projection_matrix(&camera, &window.inner_size).into(), + model_3d_shader_cursor.field("projection").binding( + create_projection_matrix(&camera, &window.inner_size).into(), + )?, )); } - shader_bindings.extend(point_light_query.iter().enumerate().flat_map( - |(point_light_index, (point_light, point_light_world_pos))| { - let point_light_shader_cursor = lighting_shader_cursor - .field("point_lights") - .element(point_light_index); - - let phong_shader_cursor = point_light_shader_cursor.field("phong"); - - let attenuation_props_shader_cursor = - point_light_shader_cursor.field("attenuation_props"); - - [ - ( - phong_shader_cursor.field("diffuse"), - point_light.diffuse.clone().into(), - ), - ( - phong_shader_cursor.field("specular"), - point_light.specular.clone().into(), - ), - ( - point_light_shader_cursor.field("position"), - (point_light_world_pos.position + point_light.local_position) - .into(), - ), - ( - attenuation_props_shader_cursor.field("constant"), - point_light.attenuation_params.constant.into(), - ), - ( - attenuation_props_shader_cursor.field("linear"), - point_light.attenuation_params.linear.into(), - ), - ( - attenuation_props_shader_cursor.field("quadratic"), - point_light.attenuation_params.quadratic.into(), - ), - ] - }, - )); - - shader_bindings.extend(directional_light_query.iter().enumerate().flat_map( - |(directional_light_index, (directional_light,))| { - let directional_light_shader_cursor = lighting_shader_cursor - .field("directional_lights") - .element(directional_light_index); - - let phong_shader_cursor = directional_light_shader_cursor.field("phong"); - - [ - ( - phong_shader_cursor.field("diffuse"), - directional_light.diffuse.clone().into(), - ), - ( - phong_shader_cursor.field("specular"), - directional_light.specular.clone().into(), - ), - ( - directional_light_shader_cursor.field("direction"), - directional_light.direction.into(), - ), - ] - }, - )); + shader_bindings + .bindings + .reserve(point_light_query.iter().count() * 6); - shader_bindings.bindings.push(( - shader_cursor.field("ambient_map").into_binding_location(), - ShaderBindingValue::Texture( - model_material - .ambient_map - .as_ref() - .map(|ambient_map| ambient_map.clone()) - .unwrap_or_else(|| { - assets - .get_handle_to_loaded(TEXTURE_WHITE_1X1_ASSET_LABEL.clone()) - .expect("Not possible") - }) - .id() - .into(), - ), - )); + for (point_light_index, (point_light, point_light_world_pos)) in + point_light_query.iter().enumerate() + { + let point_light_shader_cursor = lighting_shader_cursor + .field("point_lights") + .element(point_light_index); + + let phong_shader_cursor = point_light_shader_cursor.field("phong"); + + let attenuation_props_shader_cursor = + point_light_shader_cursor.field("attenuation_props"); + + shader_bindings.bindings.extend([ + phong_shader_cursor + .field("diffuse") + .binding(point_light.diffuse.clone().into())?, + phong_shader_cursor + .field("specular") + .binding(point_light.specular.clone().into())?, + point_light_shader_cursor.field("position").binding( + (point_light_world_pos.position + point_light.local_position).into(), + )?, + attenuation_props_shader_cursor + .field("constant") + .binding(point_light.attenuation_params.constant.into())?, + attenuation_props_shader_cursor + .field("linear") + .binding(point_light.attenuation_params.linear.into())?, + attenuation_props_shader_cursor + .field("quadratic") + .binding(point_light.attenuation_params.quadratic.into())?, + ]); + } - shader_bindings.bindings.push(( - shader_cursor.field("diffuse_map").into_binding_location(), - ShaderBindingValue::Texture( - model_material - .diffuse_map - .as_ref() - .map(|diffuse_map| diffuse_map.clone()) - .unwrap_or_else(|| { - assets - .get_handle_to_loaded(TEXTURE_WHITE_1X1_ASSET_LABEL.clone()) - .expect("Not possible") - }) - .id() - .into(), - ), - )); + shader_bindings + .bindings + .reserve(directional_light_query.iter().count() * 3); - shader_bindings.bindings.push(( - shader_cursor.field("specular_map").into_binding_location(), - ShaderBindingValue::Texture( - model_material - .specular_map - .as_ref() - .map(|specular_map| specular_map.clone()) - .unwrap_or_else(|| { - assets - .get_handle_to_loaded(TEXTURE_WHITE_1X1_ASSET_LABEL.clone()) - .expect("Not possible") - }) - .id() - .into(), - ), - )); + for (directional_light_index, (directional_light,)) in + directional_light_query.iter().enumerate() + { + let directional_light_shader_cursor = lighting_shader_cursor + .field("directional_lights") + .element(directional_light_index); + + let phong_shader_cursor = directional_light_shader_cursor.field("phong"); + + shader_bindings.bindings.extend([ + phong_shader_cursor + .field("diffuse") + .binding(directional_light.diffuse.clone().into())?, + phong_shader_cursor + .field("specular") + .binding(directional_light.specular.clone().into())?, + directional_light_shader_cursor + .field("direction") + .binding(directional_light.direction.into())?, + ]); + } + + shader_bindings.bindings.push( + shader_cursor + .field("ambient_map") + .binding(ShaderBindingValue::Texture( + model_material + .ambient_map + .as_ref() + .map(|ambient_map| ambient_map.clone()) + .unwrap_or_else(|| { + assets + .get_handle_to_loaded( + TEXTURE_WHITE_1X1_ASSET_LABEL.clone(), + ) + .expect("Not possible") + }) + .id() + .into(), + ))?, + ); + + shader_bindings.bindings.push( + shader_cursor + .field("diffuse_map") + .binding(ShaderBindingValue::Texture( + model_material + .diffuse_map + .as_ref() + .map(|diffuse_map| diffuse_map.clone()) + .unwrap_or_else(|| { + assets + .get_handle_to_loaded( + TEXTURE_WHITE_1X1_ASSET_LABEL.clone(), + ) + .expect("Not possible") + }) + .id() + .into(), + ))?, + ); + + shader_bindings.bindings.push( + shader_cursor + .field("specular_map") + .binding(ShaderBindingValue::Texture( + model_material + .specular_map + .as_ref() + .map(|specular_map| specular_map.clone()) + .unwrap_or_else(|| { + assets + .get_handle_to_loaded( + TEXTURE_WHITE_1X1_ASSET_LABEL.clone(), + ) + .expect("Not possible") + }) + .id() + .into(), + ))?, + ); if !has_pending_shader_bindings_comp { actions.add_components(entity_id, (shader_bindings.clone(),)); diff --git a/engine/src/windowing.rs b/engine/src/windowing.rs index adc5132..6997f73 100644 --- a/engine/src/windowing.rs +++ b/engine/src/windowing.rs @@ -518,7 +518,7 @@ impl Context }; }) { - tracing::error!("Failed to create windowing app thread: {err}"); + tracing::error!("Failed to create windowing app thread: {:#}", crate::Error::new(err)); return Self { shared_state, @@ -569,7 +569,7 @@ impl Context unreachable!(); }; - tracing::error!("Error in windowing app thread: {err}"); + tracing::error!("Error in windowing app thread: {:#}", crate::Error::new(err)); } else { tracing::error!("Windowing app initialization aborted unexpectedly"); } @@ -728,7 +728,7 @@ impl App ) { Ok(window) => window, Err(err) => { - tracing::error!("Failed to create window: {err}"); + tracing::error!("Failed to create window: {:#}", crate::Error::new(err)); continue; } }, @@ -953,7 +953,8 @@ impl ApplicationHandler for App cold_path(); tracing::error!( window_id=?window_id, - "Failed to lock cursor position: {err}" + "Failed to lock cursor position: {:#}", + crate::Error::new(err) ); }; } |
