1use crate::blur_pipeline::BlurPipeline;
14use crate::border::BorderRenderer;
15use crate::chain_textures::ChainTextures;
16use crate::comp_pipeline::CompPipeline;
17use crate::custom_shape::{CustomShapeBatch, CustomShapeInstance, CustomShapeRenderer};
18use crate::custom_wave::{CustomWaveBatch, CustomWaveRenderer, CustomWaveVertex};
19use crate::error::Result;
20use crate::gpu_context::GpuContext;
21use crate::motion_vector::MotionVectorRenderer;
22use crate::sprite_pipeline::{
23 SpriteDrawCmd, SpriteFrame, SpritePipeline, SpritePool, build_sprite_uniform,
24};
25use crate::warp_pipeline::{WarpPipeline, WarpVertex};
26use crate::waveform::{
27 NUM_WAVE_SAMPLES, WaveUniforms, WaveformMode, WaveformRenderer, apply_smoothing,
28 build_uniforms as build_wave_uniforms,
29};
30
31use crate::config::{RenderState, WaveParams};
32use crate::warp_mesh::WarpMesh;
33use onedrop_codegen::ShaderUniforms;
34
35pub struct RenderChain {
38 textures: ChainTextures,
43 warp: WarpPipeline,
44 blur: BlurPipeline,
45 comp: CompPipeline,
46 waveform: WaveformRenderer,
47 custom_wave: CustomWaveRenderer,
48 custom_shape: CustomShapeRenderer,
49 border: BorderRenderer,
50 motion_vector: MotionVectorRenderer,
51 wave_samples: Vec<f32>,
54 wave_volume: f32,
56 last_warp_field: Option<(u32, u32, Vec<WarpVertex>)>,
61}
62
63impl RenderChain {
64 pub fn new(gpu: &GpuContext, mesh: &WarpMesh) -> Result<Self> {
74 let textures = ChainTextures::new(&gpu.device, &gpu.config);
75 Self::with_textures(gpu, mesh, textures)
76 }
77
78 pub fn with_textures(
83 gpu: &GpuContext,
84 mesh: &WarpMesh,
85 textures: ChainTextures,
86 ) -> Result<Self> {
87 let warp = WarpPipeline::new(
88 &gpu.device,
89 gpu.config.texture_format.to_wgpu(),
90 &textures.prev_texture_view,
91 mesh,
92 )?;
93
94 let comp = CompPipeline::new(
95 &gpu.device,
96 &gpu.queue,
97 gpu.config.texture_format.to_wgpu(),
98 &textures.render_texture_view,
99 &gpu.comp_aux_views_for(&textures),
100 )?;
101
102 let blur = BlurPipeline::new(
103 &gpu.device,
104 gpu.config.texture_format.to_wgpu(),
105 gpu.config.width,
106 gpu.config.height,
107 &textures.render_texture_view,
108 &textures.blur1_texture_view,
109 &textures.blur2_texture_view,
110 &textures.blur3_texture_view,
111 &textures.blur1_scratch_texture_view,
112 &textures.blur2_scratch_texture_view,
113 &textures.blur3_scratch_texture_view,
114 );
115
116 let waveform = WaveformRenderer::new(&gpu.device, gpu.config.texture_format.to_wgpu());
117 let custom_wave = CustomWaveRenderer::new(&gpu.device, gpu.config.texture_format.to_wgpu());
118 let custom_shape = CustomShapeRenderer::new(
119 &gpu.device,
120 gpu.config.texture_format.to_wgpu(),
121 &textures.prev_texture_view,
122 );
123 let border = BorderRenderer::new(&gpu.device, gpu.config.texture_format.to_wgpu());
124 let motion_vector =
125 MotionVectorRenderer::new(&gpu.device, gpu.config.texture_format.to_wgpu());
126
127 Ok(Self {
128 textures,
129 warp,
130 blur,
131 comp,
132 waveform,
133 custom_wave,
134 custom_shape,
135 border,
136 motion_vector,
137 wave_samples: vec![0.0; NUM_WAVE_SAMPLES],
138 wave_volume: 0.0,
139 last_warp_field: None,
140 })
141 }
142
143 pub fn textures(&self) -> &ChainTextures {
147 &self.textures
148 }
149
150 pub fn update_warp_vertices(
155 &mut self,
156 queue: &wgpu::Queue,
157 cols: u32,
158 rows: u32,
159 vertices: &[WarpVertex],
160 ) {
161 self.warp.update_vertices(queue, vertices);
162 match self.last_warp_field.as_mut() {
166 Some((c, r, v)) => {
167 *c = cols;
168 *r = rows;
169 v.clear();
170 v.extend_from_slice(vertices);
171 }
172 None => {
173 self.last_warp_field = Some((cols, rows, vertices.to_vec()));
174 }
175 }
176 }
177
178 pub fn rebuild_warp_mesh(&mut self, device: &wgpu::Device, mesh: &WarpMesh) {
181 self.warp.rebuild_mesh(device, mesh);
182 }
183
184 pub fn update_waveform_samples(
190 &mut self,
191 queue: &wgpu::Queue,
192 samples: &[f32],
193 instantaneous_volume: f32,
194 wave_params: WaveParams,
195 ) {
196 let n = samples.len().min(NUM_WAVE_SAMPLES);
197 self.wave_samples.clear();
198 self.wave_samples.extend_from_slice(&samples[..n]);
199 self.wave_samples.resize(NUM_WAVE_SAMPLES, 0.0);
200 apply_smoothing(&mut self.wave_samples, wave_params.smoothing);
201 self.wave_volume = instantaneous_volume.clamp(0.0, 1.0);
202 self.waveform.update_wave_samples(queue, &self.wave_samples);
203 }
204
205 pub fn update_waveform_samples_lr(
214 &mut self,
215 queue: &wgpu::Queue,
216 left: &[f32],
217 right: &[f32],
218 instantaneous_volume: f32,
219 wave_params: WaveParams,
220 ) {
221 let nl = left.len().min(NUM_WAVE_SAMPLES);
225 self.wave_samples.clear();
226 self.wave_samples.extend_from_slice(&left[..nl]);
227 self.wave_samples.resize(NUM_WAVE_SAMPLES, 0.0);
228 apply_smoothing(&mut self.wave_samples, wave_params.smoothing);
229
230 let mut right_samples = vec![0.0f32; NUM_WAVE_SAMPLES];
231 let nr = right.len().min(NUM_WAVE_SAMPLES);
232 right_samples[..nr].copy_from_slice(&right[..nr]);
233 apply_smoothing(&mut right_samples, wave_params.smoothing);
234
235 self.wave_volume = instantaneous_volume.clamp(0.0, 1.0);
236 self.waveform
237 .update_wave_samples_lr(queue, &self.wave_samples, &right_samples);
238 }
239
240 pub fn wave_samples(&self) -> &[f32] {
241 &self.wave_samples
242 }
243
244 pub fn wave_volume(&self) -> f32 {
245 self.wave_volume
246 }
247
248 pub fn update_custom_waves(
250 &mut self,
251 queue: &wgpu::Queue,
252 vertices: &[CustomWaveVertex],
253 batches: &[CustomWaveBatch],
254 ) {
255 self.custom_wave.update(queue, vertices, batches);
256 }
257
258 pub fn custom_wave_vertex_count(&self) -> u32 {
259 self.custom_wave.vertex_count()
260 }
261
262 pub fn custom_wave_batch_count(&self) -> usize {
263 self.custom_wave.batch_count()
264 }
265
266 pub fn update_custom_shapes(
268 &mut self,
269 queue: &wgpu::Queue,
270 instances: &[CustomShapeInstance],
271 batches: &[CustomShapeBatch],
272 aspect: f32,
273 ) {
274 self.custom_shape.update(queue, instances, batches, aspect);
275 }
276
277 pub fn custom_shape_instance_count(&self) -> u32 {
278 self.custom_shape.instance_count()
279 }
280
281 pub fn custom_shape_batch_count(&self) -> usize {
282 self.custom_shape.batch_count()
283 }
284
285 pub fn border_batch_count(&self) -> usize {
286 self.border.batch_count()
287 }
288
289 pub fn motion_vector_segment_count(&self) -> u32 {
290 self.motion_vector.segment_count()
291 }
292
293 pub fn comp_pipeline(&self) -> &CompPipeline {
297 &self.comp
298 }
299
300 pub fn comp_pipeline_mut(&mut self) -> &mut CompPipeline {
301 &mut self.comp
302 }
303
304 pub fn warp_pipeline(&self) -> &WarpPipeline {
307 &self.warp
308 }
309
310 pub fn warp_pipeline_mut(&mut self) -> &mut WarpPipeline {
311 &mut self.warp
312 }
313
314 #[allow(clippy::too_many_arguments)]
322 pub fn record_passes(
323 &mut self,
324 gpu: &GpuContext,
325 encoder: &mut wgpu::CommandEncoder,
326 state: &RenderState,
327 comp_uniforms: &ShaderUniforms,
328 sprite_pipeline: &SpritePipeline,
329 sprite_pool: &SpritePool,
330 sprite_frames: &[SpriteFrame],
331 ) {
332 self.warp.update_uniforms(
334 &gpu.queue,
335 state.decay,
336 gpu.aspect_ratio(),
337 state.feedback.to_flags(),
338 );
339 self.warp.update_user_uniforms(&gpu.queue, comp_uniforms);
343 self.comp.update_uniforms(&gpu.queue, comp_uniforms);
344
345 let wave_uniforms: WaveUniforms = build_wave_uniforms(
347 state.wave,
348 self.wave_volume,
349 gpu.config.width,
350 gpu.config.height,
351 state.time,
352 );
353 self.waveform.update_uniforms(&gpu.queue, &wave_uniforms);
354
355 self.border
358 .update(&gpu.queue, state.borders, gpu.aspect_ratio());
359 let warp_field =
364 self.last_warp_field
365 .as_ref()
366 .map(|(c, r, v)| crate::motion_vector::WarpField {
367 cols: *c,
368 rows: *r,
369 vertices: v.as_slice(),
370 });
371 self.motion_vector
372 .update(&gpu.queue, state.motion_vectors, warp_field);
373
374 self.warp
376 .render(encoder, &self.textures.render_texture_view);
377
378 let wp = state.wave;
380 let is_dots = wp.dots || WaveformMode::from_i32(wp.mode) == WaveformMode::ExplosiveHash;
381 if wp.split_lr {
382 let mut left_uniforms = wave_uniforms;
390 left_uniforms.wave_y -= 0.25;
391 left_uniforms.sample_offset = 0;
392 self.waveform.update_uniforms(&gpu.queue, &left_uniforms);
393 self.waveform.render_with_blend(
394 encoder,
395 &self.textures.render_texture_view,
396 is_dots,
397 wp.additive,
398 );
399
400 let mut right_uniforms = wave_uniforms;
401 right_uniforms.wave_y += 0.25;
402 right_uniforms.sample_offset = NUM_WAVE_SAMPLES as u32;
403 self.waveform.update_uniforms(&gpu.queue, &right_uniforms);
404 self.waveform.render_with_blend(
405 encoder,
406 &self.textures.render_texture_view,
407 is_dots,
408 wp.additive,
409 );
410 } else {
411 self.waveform.render_with_blend(
412 encoder,
413 &self.textures.render_texture_view,
414 is_dots,
415 wp.additive,
416 );
417 if WaveformMode::from_i32(wp.mode).is_double_pass() {
418 let mut mirrored = wave_uniforms;
419 mirrored.wave_y = (2.0 * wp.y) - wave_uniforms.wave_y;
420 mirrored.wave_scale = -mirrored.wave_scale;
421 self.waveform.update_uniforms(&gpu.queue, &mirrored);
422 self.waveform.render_with_blend(
423 encoder,
424 &self.textures.render_texture_view,
425 is_dots,
426 wp.additive,
427 );
428 }
429 }
430
431 self.custom_wave
433 .render(encoder, &self.textures.render_texture_view);
434
435 self.custom_shape
437 .render(encoder, &self.textures.render_texture_view);
438
439 self.border
441 .render(encoder, &self.textures.render_texture_view);
442 self.motion_vector
443 .render(encoder, &self.textures.render_texture_view);
444
445 if !sprite_frames.is_empty() {
452 let cmds: Vec<SpriteDrawCmd> = sprite_frames
453 .iter()
454 .map(|f| {
455 let tex = sprite_pool.get_or_fallback(f.texture_index);
456 let uniform = build_sprite_uniform(
457 f.x,
458 f.y,
459 f.sx,
460 f.sy,
461 f.rot,
462 f.rgba,
463 tex.width,
464 tex.height,
465 gpu.config.width,
466 gpu.config.height,
467 );
468 SpriteDrawCmd {
469 uniform,
470 texture_view: &tex.view,
471 blend: f.blend,
472 burn: f.burn,
473 }
474 })
475 .collect();
476 sprite_pipeline.record(
477 encoder,
478 &gpu.queue,
479 &gpu.device,
480 &self.textures.render_texture_view,
481 sprite_pool.sampler(),
482 &cmds,
483 );
484 }
485
486 self.blur.render(
490 encoder,
491 &self.textures.blur1_texture_view,
492 &self.textures.blur2_texture_view,
493 &self.textures.blur3_texture_view,
494 &self.textures.blur1_scratch_texture_view,
495 &self.textures.blur2_scratch_texture_view,
496 &self.textures.blur3_scratch_texture_view,
497 );
498
499 self.comp.render(encoder, &self.textures.final_texture_view);
502 }
503
504 pub fn copy_to_prev(&self, encoder: &mut wgpu::CommandEncoder, gpu: &GpuContext) {
508 self.textures.copy_to_prev(encoder, &gpu.config);
509 self.textures.copy_blur_to_prev(encoder, &gpu.config);
515 }
516
517 pub fn resize(&mut self, gpu: &GpuContext) {
521 self.textures.resize(&gpu.device, &gpu.config);
522 self.warp
523 .rebind_prev_texture(&gpu.device, &self.textures.prev_texture_view);
524 self.comp.rebind_input_texture(
525 &gpu.device,
526 &self.textures.render_texture_view,
527 &gpu.comp_aux_views_for(&self.textures),
528 );
529 self.blur.rebind(
530 &gpu.device,
531 &gpu.queue,
532 gpu.config.width,
533 gpu.config.height,
534 &self.textures.render_texture_view,
535 &self.textures.blur1_texture_view,
536 &self.textures.blur2_texture_view,
537 &self.textures.blur1_scratch_texture_view,
538 &self.textures.blur2_scratch_texture_view,
539 &self.textures.blur3_scratch_texture_view,
540 );
541 self.custom_shape
543 .rebind_prev_texture(&gpu.device, &self.textures.prev_texture_view);
544 }
545}