1use arrayvec::ArrayVec;
17use glam::{UVec2, Vec4};
18use rend3::{
19 format_sso,
20 graph::{DataHandle, ReadyData, RenderGraph, RenderTargetDescriptor, RenderTargetHandle},
21 types::{SampleCount, TextureFormat, TextureUsages},
22 ProfileData, Renderer,
23};
24use wgpu::{BindGroup, Buffer};
25
26use crate::{
27 common, culling, pbr,
28 skinning::{self, GpuSkinner, SkinningOutput},
29 skybox, tonemapping,
30};
31
32pub struct PerTransparencyInfo {
35 ty: pbr::TransparencyType,
36 pre_cull: DataHandle<Buffer>,
37 shadow_cull: Vec<DataHandle<culling::PerMaterialArchetypeData>>,
38 cull: DataHandle<culling::PerMaterialArchetypeData>,
39}
40
41pub struct BaseRenderGraph {
45 pub interfaces: common::WholeFrameInterfaces,
46 pub samplers: common::Samplers,
47 pub gpu_culler: ProfileData<(), culling::GpuCuller>,
48 pub gpu_skinner: GpuSkinner,
49}
50
51impl BaseRenderGraph {
52 pub fn new(renderer: &Renderer) -> Self {
53 profiling::scope!("DefaultRenderGraphData::new");
54
55 let interfaces = common::WholeFrameInterfaces::new(&renderer.device);
56
57 let samplers = common::Samplers::new(&renderer.device);
58
59 let gpu_culler = renderer
60 .profile
61 .into_data(|| (), || culling::GpuCuller::new(&renderer.device));
62
63 let gpu_skinner = GpuSkinner::new(&renderer.device);
64
65 Self {
66 interfaces,
67 samplers,
68 gpu_culler,
69 gpu_skinner,
70 }
71 }
72
73 #[allow(clippy::too_many_arguments)]
76 pub fn add_to_graph<'node>(
77 &'node self,
78 graph: &mut RenderGraph<'node>,
79 ready: &ReadyData,
80 pbr: &'node crate::pbr::PbrRoutine,
81 skybox: Option<&'node crate::skybox::SkyboxRoutine>,
82 tonemapping: &'node crate::tonemapping::TonemappingRoutine,
83 resolution: UVec2,
84 samples: SampleCount,
85 ambient: Vec4,
86 ) {
87 let state = BaseRenderGraphIntermediateState::new(graph, ready, resolution, samples);
89
90 state.pre_skinning(graph);
92 state.pbr_pre_culling(graph);
93 state.create_frame_uniforms(graph, self, ambient);
94
95 state.skinning(graph, self);
97
98 state.pbr_shadow_culling(graph, self, pbr);
100 state.pbr_culling(graph, self, pbr);
101
102 state.pbr_shadow_rendering(graph, pbr);
104 state.pbr_prepass_rendering(graph, pbr, samples);
105
106 state.skybox(graph, skybox, samples);
108
109 state.pbr_forward_rendering(graph, pbr, samples);
111
112 let surface = graph.add_surface_texture();
114 state.tonemapping(graph, tonemapping, surface);
115 }
116}
117
118pub struct BaseRenderGraphIntermediateState {
123 pub per_transparency: ArrayVec<PerTransparencyInfo, 3>,
124 pub shadow_uniform_bg: DataHandle<BindGroup>,
125 pub forward_uniform_bg: DataHandle<BindGroup>,
126 pub color: RenderTargetHandle,
127 pub resolve: Option<RenderTargetHandle>,
128 pub depth: RenderTargetHandle,
129 pub pre_skinning_buffers: DataHandle<skinning::PreSkinningBuffers>,
130 pub skinned_data: DataHandle<skinning::SkinningOutput>,
131}
132impl BaseRenderGraphIntermediateState {
133 pub fn new(graph: &mut RenderGraph<'_>, ready: &ReadyData, resolution: UVec2, samples: SampleCount) -> Self {
135 let shadow_count = ready.directional_light_cameras.len();
137
138 let mut per_transparency = ArrayVec::new();
140 for ty in [
141 pbr::TransparencyType::Opaque,
142 pbr::TransparencyType::Cutout,
143 pbr::TransparencyType::Blend,
144 ] {
145 per_transparency.push(PerTransparencyInfo {
146 ty,
147 pre_cull: graph.add_data(),
148 shadow_cull: {
149 let mut shadows = Vec::with_capacity(shadow_count);
150 shadows.resize_with(shadow_count, || graph.add_data());
151 shadows
152 },
153 cull: graph.add_data(),
154 })
155 }
156
157 let shadow_uniform_bg = graph.add_data::<BindGroup>();
159 let forward_uniform_bg = graph.add_data::<BindGroup>();
160
161 let color = graph.add_render_target(RenderTargetDescriptor {
163 label: Some("hdr color".into()),
164 resolution,
165 samples,
166 format: TextureFormat::Rgba16Float,
167 usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING,
168 });
169 let resolve = samples.needs_resolve().then(|| {
170 graph.add_render_target(RenderTargetDescriptor {
171 label: Some("hdr resolve".into()),
172 resolution,
173 samples: SampleCount::One,
174 format: TextureFormat::Rgba16Float,
175 usage: TextureUsages::RENDER_ATTACHMENT | TextureUsages::TEXTURE_BINDING,
176 })
177 });
178 let depth = graph.add_render_target(RenderTargetDescriptor {
179 label: Some("hdr depth".into()),
180 resolution,
181 samples,
182 format: TextureFormat::Depth32Float,
183 usage: TextureUsages::RENDER_ATTACHMENT,
184 });
185
186 let pre_skinning_buffers = graph.add_data::<skinning::PreSkinningBuffers>();
187 let skinned_data = graph.add_data::<SkinningOutput>();
188
189 Self {
190 per_transparency,
191 shadow_uniform_bg,
192 forward_uniform_bg,
193 color,
194 resolve,
195 depth,
196 pre_skinning_buffers,
197 skinned_data,
198 }
199 }
200
201 pub fn pbr_pre_culling(&self, graph: &mut RenderGraph<'_>) {
203 for trans in &self.per_transparency {
204 crate::pre_cull::add_to_graph::<pbr::PbrMaterial>(
205 graph,
206 trans.ty as u64,
207 trans.ty.to_sorting(),
208 &format_sso!("{:?}", trans.ty),
209 trans.pre_cull,
210 );
211 }
212 }
213
214 pub fn pre_skinning(&self, graph: &mut RenderGraph<'_>) {
216 crate::skinning::add_pre_skin_to_graph(graph, self.pre_skinning_buffers);
217 }
218
219 pub fn create_frame_uniforms<'node>(
221 &self,
222 graph: &mut RenderGraph<'node>,
223 base: &'node BaseRenderGraph,
224 ambient: Vec4,
225 ) {
226 crate::uniforms::add_to_graph(
227 graph,
228 self.shadow_uniform_bg,
229 self.forward_uniform_bg,
230 &base.interfaces,
231 &base.samplers,
232 ambient,
233 );
234 }
235
236 pub fn pbr_shadow_culling<'node>(
238 &self,
239 graph: &mut RenderGraph<'node>,
240 base: &'node BaseRenderGraph,
241 pbr: &'node pbr::PbrRoutine,
242 ) {
243 for trans in &self.per_transparency[0..2] {
244 for (shadow_index, &shadow_culled) in trans.shadow_cull.iter().enumerate() {
245 crate::culling::add_culling_to_graph::<pbr::PbrMaterial>(
246 graph,
247 trans.pre_cull,
248 shadow_culled,
249 self.skinned_data,
250 &pbr.per_material,
251 &base.gpu_culler,
252 Some(shadow_index),
253 trans.ty as u64,
254 trans.ty.to_sorting(),
255 &format_sso!("Shadow Culling S{} {:?}", shadow_index, trans.ty),
256 );
257 }
258 }
259 }
260
261 pub fn skinning<'node>(&self, graph: &mut RenderGraph<'node>, base: &'node BaseRenderGraph) {
262 crate::skinning::add_skinning_to_graph(graph, &base.gpu_skinner, self.pre_skinning_buffers, self.skinned_data);
263 }
264
265 pub fn pbr_culling<'node>(
267 &self,
268 graph: &mut RenderGraph<'node>,
269 base: &'node BaseRenderGraph,
270 pbr: &'node pbr::PbrRoutine,
271 ) {
272 for trans in &self.per_transparency {
273 crate::culling::add_culling_to_graph::<pbr::PbrMaterial>(
274 graph,
275 trans.pre_cull,
276 trans.cull,
277 self.skinned_data,
278 &pbr.per_material,
279 &base.gpu_culler,
280 None,
281 trans.ty as u64,
282 trans.ty.to_sorting(),
283 &format_sso!("Primary Culling {:?}", trans.ty),
284 );
285 }
286 }
287
288 pub fn pbr_shadow_rendering<'node>(&self, graph: &mut RenderGraph<'node>, pbr: &'node pbr::PbrRoutine) {
290 for trans in &self.per_transparency[0..2] {
291 for (shadow_index, &shadow_culled) in trans.shadow_cull.iter().enumerate() {
292 pbr.depth_pipelines.add_shadow_rendering_to_graph(
293 graph,
294 matches!(trans.ty, pbr::TransparencyType::Cutout),
295 shadow_index,
296 self.shadow_uniform_bg,
297 shadow_culled,
298 );
299 }
300 }
301 }
302
303 pub fn pbr_prepass_rendering<'node>(
305 &self,
306 graph: &mut RenderGraph<'node>,
307 pbr: &'node pbr::PbrRoutine,
308 samples: SampleCount,
309 ) {
310 for trans in &self.per_transparency[0..2] {
311 pbr.depth_pipelines.add_prepass_to_graph(
312 graph,
313 self.forward_uniform_bg,
314 trans.cull,
315 samples,
316 matches!(trans.ty, pbr::TransparencyType::Cutout),
317 self.color,
318 self.resolve,
319 self.depth,
320 );
321 }
322 }
323
324 pub fn skybox<'node>(
326 &self,
327 graph: &mut RenderGraph<'node>,
328 skybox: Option<&'node skybox::SkyboxRoutine>,
329 samples: SampleCount,
330 ) {
331 if let Some(skybox) = skybox {
332 skybox.add_to_graph(
333 graph,
334 self.color,
335 self.resolve,
336 self.depth,
337 self.forward_uniform_bg,
338 samples,
339 );
340 }
341 }
342
343 pub fn pbr_forward_rendering<'node>(
345 &self,
346 graph: &mut RenderGraph<'node>,
347 pbr: &'node pbr::PbrRoutine,
348 samples: SampleCount,
349 ) {
350 for trans in &self.per_transparency {
351 let inner = match trans.ty {
352 pbr::TransparencyType::Opaque => &pbr.opaque_routine,
353 pbr::TransparencyType::Cutout => &pbr.cutout_routine,
354 pbr::TransparencyType::Blend => &pbr.blend_routine,
355 };
356
357 inner.add_forward_to_graph(
358 graph,
359 self.forward_uniform_bg,
360 trans.cull,
361 None,
362 &format_sso!("PBR Forward {:?}", trans.ty),
363 samples,
364 self.color,
365 self.resolve,
366 self.depth,
367 );
368 }
369 }
370
371 pub fn tonemapping<'node>(
373 &self,
374 graph: &mut RenderGraph<'node>,
375 tonemapping: &'node tonemapping::TonemappingRoutine,
376 target: RenderTargetHandle,
377 ) {
378 tonemapping.add_to_graph(
379 graph,
380 self.resolve.unwrap_or(self.color),
381 target,
382 self.forward_uniform_bg,
383 );
384 }
385}