From dfb56bc606c5c704ff57f115859e29ee37cb7fb7 Mon Sep 17 00:00:00 2001 From: Connor Fitzgerald Date: Sat, 11 Nov 2023 00:28:38 -0500 Subject: [PATCH] Final comments --- rend3-routine/src/base.rs | 23 ++++++++----- rend3-routine/src/common/camera.rs | 36 ++++++++++++++++++++ rend3-routine/src/common/mod.rs | 2 ++ rend3-routine/src/culling/batching.rs | 44 +++++++++++++++++-------- rend3-routine/src/culling/culler.rs | 47 ++++++++++++++------------- rend3-routine/src/forward.rs | 8 ++--- rend3-types/src/lib.rs | 5 +-- rend3/src/graph/store.rs | 5 +-- rend3/src/managers/object.rs | 10 +----- 9 files changed, 115 insertions(+), 65 deletions(-) create mode 100644 rend3-routine/src/common/camera.rs diff --git a/rend3-routine/src/base.rs b/rend3-routine/src/base.rs index 1a704765..6252db3c 100644 --- a/rend3-routine/src/base.rs +++ b/rend3-routine/src/base.rs @@ -27,7 +27,12 @@ use rend3::{ }; use wgpu::{BindGroup, Buffer}; -use crate::{common, culling, forward::RoutineAddToGraphArgs, pbr, skinning, skybox, tonemapping}; +use crate::{ + common::{self, CameraIndex}, + culling, + forward::RoutineAddToGraphArgs, + pbr, skinning, skybox, tonemapping, +}; #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub struct DepthTargets { @@ -288,7 +293,7 @@ impl BaseRenderGraphIntermediateState { for (shadow_index, shadow) in eval_output.shadows.iter().enumerate() { base.gpu_culler.add_object_uniform_upload_to_graph::( graph, - Some(shadow_index), + CameraIndex::Shadow(shadow_index as u32), UVec2::splat(shadow.map.size), SampleCount::One, &format_sso!("Shadow Culling S{}", shadow_index), @@ -303,7 +308,7 @@ impl BaseRenderGraphIntermediateState { graph, shadow_culled, self.shadow, - Some(shadow_index), + CameraIndex::Shadow(shadow_index as u32), &format_sso!("Shadow Culling S{}", shadow_index), ); } @@ -322,7 +327,7 @@ impl BaseRenderGraphIntermediateState { ) { base.gpu_culler.add_object_uniform_upload_to_graph::( graph, - None, + CameraIndex::Viewport, resolution, samples, "Uniform Bake", @@ -335,7 +340,7 @@ impl BaseRenderGraphIntermediateState { graph, self.cull, self.depth.single_sample_mipped, - None, + CameraIndex::Viewport, "Primary Culling", ); } @@ -376,7 +381,7 @@ impl BaseRenderGraphIntermediateState { extra_bgs: None, label: &format!("pbr shadow renderering S{shadow_index}"), samples: SampleCount::One, - camera: Some(shadow_index), + camera: CameraIndex::Shadow(shadow_index as u32), color: None, resolve: None, depth: self @@ -423,7 +428,7 @@ impl BaseRenderGraphIntermediateState { extra_bgs: None, label: "PBR Forward Pass 1", samples, - camera: None, + camera: CameraIndex::Viewport, color: Some(self.color), resolve: self.resolve, depth: self.depth.rendering_target(), @@ -448,7 +453,7 @@ impl BaseRenderGraphIntermediateState { extra_bgs: None, label: "PBR Forward Pass 2", samples, - camera: None, + camera: CameraIndex::Viewport, color: Some(self.color), resolve: self.resolve, depth: self.depth.rendering_target(), @@ -470,7 +475,7 @@ impl BaseRenderGraphIntermediateState { per_material: &pbr.per_material, extra_bgs: None, label: "PBR Forward", - camera: None, + camera: CameraIndex::Viewport, samples, color: Some(self.color), resolve: self.resolve, diff --git a/rend3-routine/src/common/camera.rs b/rend3-routine/src/common/camera.rs new file mode 100644 index 00000000..6f09f5cc --- /dev/null +++ b/rend3-routine/src/common/camera.rs @@ -0,0 +1,36 @@ +/// Index representing which camera we're referring to. +#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] +pub enum CameraIndex { + Viewport, + Shadow(u32), +} + +impl CameraIndex { + /// Returns `true` if the camera index is [`Viewport`]. + /// + /// [`Viewport`]: CameraIndex::Viewport + #[must_use] + pub fn is_viewport(&self) -> bool { + matches!(self, Self::Viewport) + } + + /// Returns `true` if the camera index is [`Shadow`]. + /// + /// [`Shadow`]: CameraIndex::Shadow + #[must_use] + pub fn is_shadow(&self) -> bool { + matches!(self, Self::Shadow(..)) + } + + /// Returns a shader compatible index for the camera, using u32::MAX for the viewport camera. + #[must_use] + pub fn to_shader_index(&self) -> u32 { + match *self { + Self::Viewport => u32::MAX, + Self::Shadow(index) => { + assert_ne!(index, u32::MAX, "Shadow camera index cannot be 0xFFFF_FFFF"); + index + } + } + } +} diff --git a/rend3-routine/src/common/mod.rs b/rend3-routine/src/common/mod.rs index f8a2bed8..6acc7257 100644 --- a/rend3-routine/src/common/mod.rs +++ b/rend3-routine/src/common/mod.rs @@ -1,7 +1,9 @@ //! Common utilities used throughout the crate. +mod camera; mod interfaces; mod samplers; +pub use camera::*; pub use interfaces::*; pub use samplers::*; diff --git a/rend3-routine/src/culling/batching.rs b/rend3-routine/src/culling/batching.rs index cb308bcc..cff60c9d 100644 --- a/rend3-routine/src/culling/batching.rs +++ b/rend3-routine/src/culling/batching.rs @@ -1,4 +1,4 @@ -use std::{cmp::Ordering, collections::HashMap, mem}; +use std::{cmp::Ordering, collections::HashMap}; use encase::ShaderType; use ordered_float::OrderedFloat; @@ -6,9 +6,11 @@ use rend3::{ graph::NodeExecutionContext, managers::{CameraManager, TextureBindGroupIndex}, types::{GraphDataHandle, Material, RawObjectHandle, SortingOrder, SortingReason}, - util::math::round_up, + util::{math::round_up, typedefs::FastHashMap}, }; +use crate::common::CameraIndex; + use super::{BATCH_SIZE, WORKGROUP_SIZE}; #[derive(Debug)] @@ -97,23 +99,37 @@ pub(super) struct ShaderObjectCullingInformation { pub atomic_capable: u32, } +/// Map containing the previous invocation of each object. +pub struct PerCameraPreviousInvocationsMap { + inner: FastHashMap>, +} +impl PerCameraPreviousInvocationsMap { + pub fn new() -> Self { + Self { + inner: HashMap::default(), + } + } + + pub fn get_and_reset_camera(&mut self, camera: CameraIndex) -> FastHashMap { + self.inner.remove(&camera).unwrap_or_default() + } + + pub fn set_camera(&mut self, camera: CameraIndex, previous_invocations: FastHashMap) { + self.inner.insert(camera, previous_invocations); + } +} + pub(super) fn batch_objects( ctx: &mut NodeExecutionContext, - previous_invocation_map_handle: &GraphDataHandle, HashMap>>, + previous_invocation_map_handle: &GraphDataHandle, camera: &CameraManager, - camera_idx: Option, + camera_idx: CameraIndex, ) -> ShaderBatchDatas { profiling::scope!("Batch Objects"); - let mut current_invocation_map_map = ctx.data_core.graph_storage.get_mut(previous_invocation_map_handle); - let current_invocation_map = current_invocation_map_map - .entry(camera_idx) - .or_insert_with(Default::default); - let current_invocation_map_len = current_invocation_map.len(); - let previous_invocation_map = mem::replace( - current_invocation_map, - HashMap::with_capacity(current_invocation_map_len), - ); + let mut per_camera_previous_invocation_map = ctx.data_core.graph_storage.get_mut(previous_invocation_map_handle); + let previous_invocation_map = per_camera_previous_invocation_map.get_and_reset_camera(camera_idx); + let mut current_invocation_map = FastHashMap::default(); let mut jobs = ShaderBatchDatas { jobs: Vec::new(), @@ -257,5 +273,7 @@ pub(super) fn batch_objects( }); } + per_camera_previous_invocation_map.set_camera(camera_idx, current_invocation_map); + jobs } diff --git a/rend3-routine/src/culling/culler.rs b/rend3-routine/src/culling/culler.rs index 78af256a..24feec12 100644 --- a/rend3-routine/src/culling/culler.rs +++ b/rend3-routine/src/culling/culler.rs @@ -13,7 +13,7 @@ use rend3::{ format_sso, graph::{DataHandle, DeclaredDependency, NodeExecutionContext, NodeResourceUsage, RenderGraph, RenderTargetHandle}, managers::{CameraManager, ShaderObject, TextureBindGroupIndex}, - types::{GraphDataHandle, Material, MaterialArray, RawObjectHandle, SampleCount, VERTEX_ATTRIBUTE_POSITION}, + types::{GraphDataHandle, Material, MaterialArray, SampleCount, VERTEX_ATTRIBUTE_POSITION}, util::{frustum::Frustum, math::IntegerExt, typedefs::FastHashMap}, Renderer, ShaderPreProcessor, ShaderVertexBufferConfig, }; @@ -25,10 +25,13 @@ use wgpu::{ ShaderModuleDescriptor, ShaderStages, TextureSampleType, TextureViewDimension, }; -use crate::culling::{ - batching::{batch_objects, JobSubRegion, ShaderBatchData, ShaderBatchDatas}, - suballoc::InputOutputBuffer, - WORKGROUP_SIZE, +use crate::{ + common::CameraIndex, + culling::{ + batching::{batch_objects, JobSubRegion, PerCameraPreviousInvocationsMap, ShaderBatchData, ShaderBatchDatas}, + suballoc::InputOutputBuffer, + WORKGROUP_SIZE, + }, }; #[derive(Debug)] @@ -48,10 +51,10 @@ pub struct DrawCall { #[derive(Default)] pub struct CullingBufferMap { - inner: FastHashMap, CullingBuffers>, + inner: FastHashMap, } impl CullingBufferMap { - pub fn get_buffers(&self, camera: Option) -> Option<&CullingBuffers> { + pub fn get_buffers(&self, camera: CameraIndex) -> Option<&CullingBuffers> { self.inner.get(&camera) } @@ -60,7 +63,7 @@ impl CullingBufferMap { queue: &Queue, device: &Device, encoder: &mut CommandEncoder, - camera: Option, + camera: CameraIndex, sizes: CullingBufferSizes, ) -> &mut CullingBuffers { match self.inner.entry(camera) { @@ -187,9 +190,9 @@ pub struct GpuCuller { sampler: Sampler, winding: wgpu::FrontFace, type_id: TypeId, - per_material_buffer_handle: GraphDataHandle, Arc>>, + per_material_buffer_handle: GraphDataHandle>>, pub culling_buffer_map_handle: GraphDataHandle, - previous_invocation_map_handle: GraphDataHandle, HashMap>>, + previous_invocation_map_handle: GraphDataHandle, } impl GpuCuller { @@ -405,7 +408,7 @@ impl GpuCuller { let per_material_buffer_handle = renderer.add_graph_data(HashMap::default()); let culling_buffer_map_handle = renderer.add_graph_data(CullingBufferMap::default()); - let previous_invocation_map_handle = renderer.add_graph_data(HashMap::default()); + let previous_invocation_map_handle = renderer.add_graph_data(PerCameraPreviousInvocationsMap::new()); Self { prep_bgl, @@ -425,7 +428,7 @@ impl GpuCuller { &self, ctx: &mut NodeExecutionContext, camera: &CameraManager, - camera_idx: Option, + camera_idx: CameraIndex, resolution: UVec2, samples: SampleCount, ) where @@ -477,8 +480,8 @@ impl GpuCuller { }; let culling = match camera_idx { - Some(_) => wgpu::Face::Front, - None => wgpu::Face::Back, + CameraIndex::Shadow(_) => wgpu::Face::Front, + CameraIndex::Viewport => wgpu::Face::Back, }; { @@ -487,7 +490,7 @@ impl GpuCuller { let per_camera_data = PerCameraUniform { view: camera.view(), view_proj: camera.view_proj(), - shadow_index: camera_idx.unwrap_or(u32::MAX as _) as u32, + shadow_index: camera_idx.to_shader_index(), frustum: camera.world_frustum(), resolution: resolution.as_vec2(), flags: { @@ -544,7 +547,7 @@ impl GpuCuller { ctx: &mut NodeExecutionContext, jobs: ShaderBatchDatas, depth_handle: DeclaredDependency, - camera_idx: Option, + camera_idx: CameraIndex, ) -> DrawCallSet where M: Material, @@ -707,7 +710,7 @@ impl GpuCuller { pub fn add_object_uniform_upload_to_graph<'node, M: Material>( &'node self, graph: &mut RenderGraph<'node>, - camera_idx: Option, + camera_idx: CameraIndex, resolution: UVec2, samples: SampleCount, name: &str, @@ -717,8 +720,8 @@ impl GpuCuller { node.build(move |mut ctx| { let camera = match camera_idx { - Some(i) => &ctx.eval_output.shadows[i].camera, - None => &ctx.data_core.camera_manager, + CameraIndex::Shadow(i) => &ctx.eval_output.shadows[i as usize].camera, + CameraIndex::Viewport => &ctx.data_core.camera_manager, }; self.object_uniform_upload::(&mut ctx, camera, camera_idx, resolution, samples); @@ -730,7 +733,7 @@ impl GpuCuller { graph: &mut RenderGraph<'node>, draw_calls_hdl: DataHandle>, depth_handle: RenderTargetHandle, - camera_idx: Option, + camera_idx: CameraIndex, name: &str, ) { let mut node = graph.add_node(name); @@ -739,8 +742,8 @@ impl GpuCuller { node.build(move |mut ctx| { let camera = match camera_idx { - Some(i) => &ctx.eval_output.shadows[i].camera, - None => &ctx.data_core.camera_manager, + CameraIndex::Shadow(i) => &ctx.eval_output.shadows[i as usize].camera, + CameraIndex::Viewport => &ctx.data_core.camera_manager, }; let jobs = batch_objects::(&mut ctx, &self.previous_invocation_map_handle, camera, camera_idx); diff --git a/rend3-routine/src/forward.rs b/rend3-routine/src/forward.rs index c50f696d..c33fa69c 100644 --- a/rend3-routine/src/forward.rs +++ b/rend3-routine/src/forward.rs @@ -24,7 +24,7 @@ use wgpu::{ }; use crate::{ - common::{PerMaterialArchetypeInterface, WholeFrameInterfaces}, + common::{CameraIndex, PerMaterialArchetypeInterface, WholeFrameInterfaces}, culling::{self, CullingBufferMap, DrawCall, DrawCallSet, InputOutputPartition}, }; @@ -82,7 +82,7 @@ pub struct RoutineAddToGraphArgs<'a, 'node, M> { pub color: Option, pub resolve: Option, pub depth: RenderTargetHandle, - pub camera: Option, + pub camera: CameraIndex, } /// A set of pipelines for rendering a specific combination of a material. @@ -91,7 +91,7 @@ pub struct ForwardRoutine { pub pipeline_s4: RenderPipeline, pub material_key: u64, pub culling_buffer_map_handle: GraphDataHandle, - pub draw_call_set_cache_handle: GraphDataHandle, Arc>>, + pub draw_call_set_cache_handle: GraphDataHandle>>, pub _phantom: PhantomData, } impl ForwardRoutine { @@ -204,7 +204,7 @@ impl ForwardRoutine { draw_call_set } }; - let residual = culling_output_handle.is_some() && args.camera.is_none(); + let residual = culling_output_handle.is_some() && args.camera.is_viewport(); let culling_buffer_storage = ctx.data_core.graph_storage.get(&self.culling_buffer_map_handle); diff --git a/rend3-types/src/lib.rs b/rend3-types/src/lib.rs index cfd402f8..d6664d9e 100644 --- a/rend3-types/src/lib.rs +++ b/rend3-types/src/lib.rs @@ -57,10 +57,7 @@ impl Copy for RawResourceHandle {} impl Clone for RawResourceHandle { fn clone(&self) -> Self { - Self { - idx: self.idx, - _phantom: PhantomData, - } + *self } } diff --git a/rend3/src/graph/store.rs b/rend3/src/graph/store.rs index e5b2254c..1950aecd 100644 --- a/rend3/src/graph/store.rs +++ b/rend3/src/graph/store.rs @@ -25,10 +25,7 @@ impl Copy for DataHandle {} impl Clone for DataHandle { fn clone(&self) -> Self { - Self { - idx: self.idx, - _phantom: self._phantom, - } + *self } } diff --git a/rend3/src/managers/object.rs b/rend3/src/managers/object.rs index c5c08b16..8cbb6fa8 100644 --- a/rend3/src/managers/object.rs +++ b/rend3/src/managers/object.rs @@ -55,15 +55,7 @@ impl Copy for ShaderObject {} // Manual impl so that M: !Clone impl Clone for ShaderObject { fn clone(&self) -> Self { - Self { - transform: self.transform, - bounding_sphere: self.bounding_sphere, - first_index: self.first_index, - index_count: self.index_count, - material_index: self.material_index, - vertex_attribute_start_offsets: self.vertex_attribute_start_offsets, - enabled: self.enabled, - } + *self } }