1use std::num::NonZeroU64;
11
12use super::super::RenderEngine;
13
14impl RenderEngine {
15 pub fn init_point_pipeline(&mut self) {
17 let shader_source = include_str!("../../shaders/point_sphere.wgsl");
18 let shader = self
19 .device
20 .create_shader_module(wgpu::ShaderModuleDescriptor {
21 label: Some("point sphere shader"),
22 source: wgpu::ShaderSource::Wgsl(shader_source.into()),
23 });
24
25 let bind_group_layout =
26 self.device
27 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
28 label: Some("point cloud bind group layout"),
29 entries: &[
30 wgpu::BindGroupLayoutEntry {
32 binding: 0,
33 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
34 ty: wgpu::BindingType::Buffer {
35 ty: wgpu::BufferBindingType::Uniform,
36 has_dynamic_offset: false,
37 min_binding_size: NonZeroU64::new(272),
38 },
39 count: None,
40 },
41 wgpu::BindGroupLayoutEntry {
43 binding: 1,
44 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
45 ty: wgpu::BindingType::Buffer {
46 ty: wgpu::BufferBindingType::Uniform,
47 has_dynamic_offset: false,
48 min_binding_size: NonZeroU64::new(96),
49 },
50 count: None,
51 },
52 wgpu::BindGroupLayoutEntry {
54 binding: 2,
55 visibility: wgpu::ShaderStages::VERTEX,
56 ty: wgpu::BindingType::Buffer {
57 ty: wgpu::BufferBindingType::Storage { read_only: true },
58 has_dynamic_offset: false,
59 min_binding_size: None,
60 },
61 count: None,
62 },
63 wgpu::BindGroupLayoutEntry {
65 binding: 3,
66 visibility: wgpu::ShaderStages::VERTEX,
67 ty: wgpu::BindingType::Buffer {
68 ty: wgpu::BufferBindingType::Storage { read_only: true },
69 has_dynamic_offset: false,
70 min_binding_size: None,
71 },
72 count: None,
73 },
74 ],
75 });
76
77 let pipeline_layout = self
78 .device
79 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
80 label: Some("point pipeline layout"),
81 bind_group_layouts: &[
82 &bind_group_layout,
83 &self.slice_plane_bind_group_layout,
84 &self.matcap_bind_group_layout,
85 ],
86 push_constant_ranges: &[],
87 });
88
89 let pipeline = self
90 .device
91 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
92 label: Some("point sphere pipeline"),
93 layout: Some(&pipeline_layout),
94 vertex: wgpu::VertexState {
95 module: &shader,
96 entry_point: Some("vs_main"),
97 buffers: &[],
98 compilation_options: wgpu::PipelineCompilationOptions::default(),
99 },
100 fragment: Some(wgpu::FragmentState {
101 module: &shader,
102 entry_point: Some("fs_main"),
103 targets: &[Some(wgpu::ColorTargetState {
104 format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState::REPLACE),
106 write_mask: wgpu::ColorWrites::ALL,
107 })],
108 compilation_options: wgpu::PipelineCompilationOptions::default(),
109 }),
110 primitive: wgpu::PrimitiveState {
111 topology: wgpu::PrimitiveTopology::TriangleList,
112 strip_index_format: None,
113 front_face: wgpu::FrontFace::Ccw,
114 cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill,
116 unclipped_depth: false,
117 conservative: false,
118 },
119 depth_stencil: Some(wgpu::DepthStencilState {
120 format: wgpu::TextureFormat::Depth24PlusStencil8,
121 depth_write_enabled: true,
122 depth_compare: wgpu::CompareFunction::Less,
123 stencil: wgpu::StencilState::default(),
124 bias: wgpu::DepthBiasState::default(),
125 }),
126 multisample: wgpu::MultisampleState::default(),
127 multiview: None,
128 cache: None,
129 });
130
131 self.point_pipeline = Some(pipeline);
132 self.point_bind_group_layout = Some(bind_group_layout);
133 }
134
135 pub fn point_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
137 self.point_bind_group_layout
138 .as_ref()
139 .expect("point pipeline not initialized")
140 }
141
142 pub fn init_vector_pipeline(&mut self) {
144 let shader_source = include_str!("../../shaders/vector_arrow.wgsl");
145 let shader = self
146 .device
147 .create_shader_module(wgpu::ShaderModuleDescriptor {
148 label: Some("vector arrow shader"),
149 source: wgpu::ShaderSource::Wgsl(shader_source.into()),
150 });
151
152 let bind_group_layout =
153 self.device
154 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
155 label: Some("vector bind group layout"),
156 entries: &[
157 wgpu::BindGroupLayoutEntry {
159 binding: 0,
160 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
161 ty: wgpu::BindingType::Buffer {
162 ty: wgpu::BufferBindingType::Uniform,
163 has_dynamic_offset: false,
164 min_binding_size: NonZeroU64::new(272),
165 },
166 count: None,
167 },
168 wgpu::BindGroupLayoutEntry {
170 binding: 1,
171 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
172 ty: wgpu::BindingType::Buffer {
173 ty: wgpu::BufferBindingType::Uniform,
174 has_dynamic_offset: false,
175 min_binding_size: NonZeroU64::new(96),
176 },
177 count: None,
178 },
179 wgpu::BindGroupLayoutEntry {
181 binding: 2,
182 visibility: wgpu::ShaderStages::VERTEX,
183 ty: wgpu::BindingType::Buffer {
184 ty: wgpu::BufferBindingType::Storage { read_only: true },
185 has_dynamic_offset: false,
186 min_binding_size: None,
187 },
188 count: None,
189 },
190 wgpu::BindGroupLayoutEntry {
192 binding: 3,
193 visibility: wgpu::ShaderStages::VERTEX,
194 ty: wgpu::BindingType::Buffer {
195 ty: wgpu::BufferBindingType::Storage { read_only: true },
196 has_dynamic_offset: false,
197 min_binding_size: None,
198 },
199 count: None,
200 },
201 ],
202 });
203
204 let pipeline_layout = self
205 .device
206 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
207 label: Some("vector pipeline layout"),
208 bind_group_layouts: &[
209 &bind_group_layout,
210 &self.slice_plane_bind_group_layout,
211 &self.matcap_bind_group_layout,
212 ],
213 push_constant_ranges: &[],
214 });
215
216 let pipeline = self
217 .device
218 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
219 label: Some("vector arrow pipeline"),
220 layout: Some(&pipeline_layout),
221 vertex: wgpu::VertexState {
222 module: &shader,
223 entry_point: Some("vs_main"),
224 buffers: &[],
225 compilation_options: wgpu::PipelineCompilationOptions::default(),
226 },
227 fragment: Some(wgpu::FragmentState {
228 module: &shader,
229 entry_point: Some("fs_main"),
230 targets: &[Some(wgpu::ColorTargetState {
231 format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState::REPLACE),
233 write_mask: wgpu::ColorWrites::ALL,
234 })],
235 compilation_options: wgpu::PipelineCompilationOptions::default(),
236 }),
237 primitive: wgpu::PrimitiveState {
238 topology: wgpu::PrimitiveTopology::TriangleList,
239 strip_index_format: None,
240 front_face: wgpu::FrontFace::Ccw,
241 cull_mode: Some(wgpu::Face::Back),
242 polygon_mode: wgpu::PolygonMode::Fill,
243 unclipped_depth: false,
244 conservative: false,
245 },
246 depth_stencil: Some(wgpu::DepthStencilState {
247 format: wgpu::TextureFormat::Depth24PlusStencil8,
248 depth_write_enabled: true,
249 depth_compare: wgpu::CompareFunction::Less,
250 stencil: wgpu::StencilState::default(),
251 bias: wgpu::DepthBiasState::default(),
252 }),
253 multisample: wgpu::MultisampleState::default(),
254 multiview: None,
255 cache: None,
256 });
257
258 self.vector_pipeline = Some(pipeline);
259 self.vector_bind_group_layout = Some(bind_group_layout);
260 }
261
262 pub fn vector_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
264 self.vector_bind_group_layout
265 .as_ref()
266 .expect("vector pipeline not initialized")
267 }
268
269 pub fn mesh_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
271 self.mesh_bind_group_layout
272 .as_ref()
273 .expect("mesh pipeline not initialized")
274 }
275
276 pub fn simple_mesh_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
278 self.simple_mesh_bind_group_layout
279 .as_ref()
280 .expect("simple mesh pipeline not initialized")
281 }
282
283 pub(crate) fn create_mesh_pipeline(&mut self) {
285 let shader_source = include_str!("../../shaders/surface_mesh.wgsl");
286 let shader = self
287 .device
288 .create_shader_module(wgpu::ShaderModuleDescriptor {
289 label: Some("surface mesh shader"),
290 source: wgpu::ShaderSource::Wgsl(shader_source.into()),
291 });
292
293 let bind_group_layout =
294 self.device
295 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
296 label: Some("mesh bind group layout"),
297 entries: &[
298 wgpu::BindGroupLayoutEntry {
300 binding: 0,
301 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
302 ty: wgpu::BindingType::Buffer {
303 ty: wgpu::BufferBindingType::Uniform,
304 has_dynamic_offset: false,
305 min_binding_size: NonZeroU64::new(272),
306 },
307 count: None,
308 },
309 wgpu::BindGroupLayoutEntry {
311 binding: 1,
312 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
313 ty: wgpu::BindingType::Buffer {
314 ty: wgpu::BufferBindingType::Uniform,
315 has_dynamic_offset: false,
316 min_binding_size: NonZeroU64::new(160),
317 },
318 count: None,
319 },
320 wgpu::BindGroupLayoutEntry {
322 binding: 2,
323 visibility: wgpu::ShaderStages::VERTEX,
324 ty: wgpu::BindingType::Buffer {
325 ty: wgpu::BufferBindingType::Storage { read_only: true },
326 has_dynamic_offset: false,
327 min_binding_size: None,
328 },
329 count: None,
330 },
331 wgpu::BindGroupLayoutEntry {
333 binding: 3,
334 visibility: wgpu::ShaderStages::VERTEX,
335 ty: wgpu::BindingType::Buffer {
336 ty: wgpu::BufferBindingType::Storage { read_only: true },
337 has_dynamic_offset: false,
338 min_binding_size: None,
339 },
340 count: None,
341 },
342 wgpu::BindGroupLayoutEntry {
344 binding: 4,
345 visibility: wgpu::ShaderStages::VERTEX,
346 ty: wgpu::BindingType::Buffer {
347 ty: wgpu::BufferBindingType::Storage { read_only: true },
348 has_dynamic_offset: false,
349 min_binding_size: None,
350 },
351 count: None,
352 },
353 wgpu::BindGroupLayoutEntry {
355 binding: 5,
356 visibility: wgpu::ShaderStages::VERTEX,
357 ty: wgpu::BindingType::Buffer {
358 ty: wgpu::BufferBindingType::Storage { read_only: true },
359 has_dynamic_offset: false,
360 min_binding_size: None,
361 },
362 count: None,
363 },
364 wgpu::BindGroupLayoutEntry {
366 binding: 6,
367 visibility: wgpu::ShaderStages::VERTEX,
368 ty: wgpu::BindingType::Buffer {
369 ty: wgpu::BufferBindingType::Storage { read_only: true },
370 has_dynamic_offset: false,
371 min_binding_size: None,
372 },
373 count: None,
374 },
375 ],
376 });
377
378 let pipeline_layout = self
379 .device
380 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
381 label: Some("mesh pipeline layout"),
382 bind_group_layouts: &[
383 &bind_group_layout,
384 &self.slice_plane_bind_group_layout,
385 &self.matcap_bind_group_layout,
386 ],
387 push_constant_ranges: &[],
388 });
389
390 let pipeline = self
391 .device
392 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
393 label: Some("surface mesh pipeline"),
394 layout: Some(&pipeline_layout),
395 vertex: wgpu::VertexState {
396 module: &shader,
397 entry_point: Some("vs_main"),
398 buffers: &[],
399 compilation_options: wgpu::PipelineCompilationOptions::default(),
400 },
401 fragment: Some(wgpu::FragmentState {
402 module: &shader,
403 entry_point: Some("fs_main"),
404 targets: &[
405 Some(wgpu::ColorTargetState {
407 format: wgpu::TextureFormat::Rgba16Float,
408 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
409 write_mask: wgpu::ColorWrites::ALL,
410 }),
411 Some(wgpu::ColorTargetState {
413 format: wgpu::TextureFormat::Rgba16Float,
414 blend: None,
415 write_mask: wgpu::ColorWrites::ALL,
416 }),
417 ],
418 compilation_options: wgpu::PipelineCompilationOptions::default(),
419 }),
420 primitive: wgpu::PrimitiveState {
421 topology: wgpu::PrimitiveTopology::TriangleList,
422 strip_index_format: None,
423 front_face: wgpu::FrontFace::Ccw,
424 cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill,
426 unclipped_depth: false,
427 conservative: false,
428 },
429 depth_stencil: Some(wgpu::DepthStencilState {
430 format: wgpu::TextureFormat::Depth24PlusStencil8,
431 depth_write_enabled: true,
432 depth_compare: wgpu::CompareFunction::Less,
433 stencil: wgpu::StencilState::default(),
434 bias: wgpu::DepthBiasState::default(),
435 }),
436 multisample: wgpu::MultisampleState::default(),
437 multiview: None,
438 cache: None,
439 });
440
441 let depth_normal_pipeline =
442 self.device
443 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
444 label: Some("surface mesh depth/normal pipeline"),
445 layout: Some(&pipeline_layout),
446 vertex: wgpu::VertexState {
447 module: &shader,
448 entry_point: Some("vs_main"),
449 buffers: &[],
450 compilation_options: wgpu::PipelineCompilationOptions::default(),
451 },
452 fragment: Some(wgpu::FragmentState {
453 module: &shader,
454 entry_point: Some("fs_main"),
455 targets: &[
456 Some(wgpu::ColorTargetState {
458 format: wgpu::TextureFormat::Rgba16Float,
459 blend: None,
460 write_mask: wgpu::ColorWrites::empty(),
461 }),
462 Some(wgpu::ColorTargetState {
464 format: wgpu::TextureFormat::Rgba16Float,
465 blend: None,
466 write_mask: wgpu::ColorWrites::ALL,
467 }),
468 ],
469 compilation_options: wgpu::PipelineCompilationOptions::default(),
470 }),
471 primitive: wgpu::PrimitiveState {
472 topology: wgpu::PrimitiveTopology::TriangleList,
473 strip_index_format: None,
474 front_face: wgpu::FrontFace::Ccw,
475 cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill,
477 unclipped_depth: false,
478 conservative: false,
479 },
480 depth_stencil: Some(wgpu::DepthStencilState {
481 format: wgpu::TextureFormat::Depth24PlusStencil8,
482 depth_write_enabled: true,
483 depth_compare: wgpu::CompareFunction::Less,
484 stencil: wgpu::StencilState::default(),
485 bias: wgpu::DepthBiasState::default(),
486 }),
487 multisample: wgpu::MultisampleState::default(),
488 multiview: None,
489 cache: None,
490 });
491
492 self.mesh_pipeline = Some(pipeline);
493 self.mesh_depth_normal_pipeline = Some(depth_normal_pipeline);
494 self.mesh_bind_group_layout = Some(bind_group_layout);
495 }
496
497 pub(crate) fn create_simple_mesh_pipeline(&mut self) {
499 let shader_source = include_str!("../../shaders/simple_mesh.wgsl");
500 let shader = self
501 .device
502 .create_shader_module(wgpu::ShaderModuleDescriptor {
503 label: Some("simple mesh shader"),
504 source: wgpu::ShaderSource::Wgsl(shader_source.into()),
505 });
506
507 let bind_group_layout =
508 self.device
509 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
510 label: Some("simple mesh bind group layout"),
511 entries: &[
512 wgpu::BindGroupLayoutEntry {
514 binding: 0,
515 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
516 ty: wgpu::BindingType::Buffer {
517 ty: wgpu::BufferBindingType::Uniform,
518 has_dynamic_offset: false,
519 min_binding_size: NonZeroU64::new(272),
520 },
521 count: None,
522 },
523 wgpu::BindGroupLayoutEntry {
525 binding: 1,
526 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
527 ty: wgpu::BindingType::Buffer {
528 ty: wgpu::BufferBindingType::Uniform,
529 has_dynamic_offset: false,
530 min_binding_size: NonZeroU64::new(96),
531 },
532 count: None,
533 },
534 wgpu::BindGroupLayoutEntry {
536 binding: 2,
537 visibility: wgpu::ShaderStages::VERTEX,
538 ty: wgpu::BindingType::Buffer {
539 ty: wgpu::BufferBindingType::Storage { read_only: true },
540 has_dynamic_offset: false,
541 min_binding_size: None,
542 },
543 count: None,
544 },
545 wgpu::BindGroupLayoutEntry {
547 binding: 3,
548 visibility: wgpu::ShaderStages::VERTEX,
549 ty: wgpu::BindingType::Buffer {
550 ty: wgpu::BufferBindingType::Storage { read_only: true },
551 has_dynamic_offset: false,
552 min_binding_size: None,
553 },
554 count: None,
555 },
556 ],
557 });
558
559 let pipeline_layout = self
560 .device
561 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
562 label: Some("simple mesh pipeline layout"),
563 bind_group_layouts: &[
564 &bind_group_layout,
565 &self.slice_plane_bind_group_layout,
566 &self.matcap_bind_group_layout,
567 ],
568 push_constant_ranges: &[],
569 });
570
571 let pipeline = self
572 .device
573 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
574 label: Some("simple mesh pipeline"),
575 layout: Some(&pipeline_layout),
576 vertex: wgpu::VertexState {
577 module: &shader,
578 entry_point: Some("vs_main"),
579 buffers: &[],
580 compilation_options: wgpu::PipelineCompilationOptions::default(),
581 },
582 fragment: Some(wgpu::FragmentState {
583 module: &shader,
584 entry_point: Some("fs_main"),
585 targets: &[
586 Some(wgpu::ColorTargetState {
588 format: wgpu::TextureFormat::Rgba16Float,
589 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
590 write_mask: wgpu::ColorWrites::ALL,
591 }),
592 Some(wgpu::ColorTargetState {
594 format: wgpu::TextureFormat::Rgba16Float,
595 blend: None,
596 write_mask: wgpu::ColorWrites::ALL,
597 }),
598 ],
599 compilation_options: wgpu::PipelineCompilationOptions::default(),
600 }),
601 primitive: wgpu::PrimitiveState {
602 topology: wgpu::PrimitiveTopology::TriangleList,
603 strip_index_format: None,
604 front_face: wgpu::FrontFace::Ccw,
605 cull_mode: None,
606 polygon_mode: wgpu::PolygonMode::Fill,
607 unclipped_depth: false,
608 conservative: false,
609 },
610 depth_stencil: Some(wgpu::DepthStencilState {
611 format: wgpu::TextureFormat::Depth24PlusStencil8,
612 depth_write_enabled: true,
613 depth_compare: wgpu::CompareFunction::Less,
614 stencil: wgpu::StencilState::default(),
615 bias: wgpu::DepthBiasState::default(),
616 }),
617 multisample: wgpu::MultisampleState::default(),
618 multiview: None,
619 cache: None,
620 });
621
622 self.simple_mesh_pipeline = Some(pipeline);
623 self.simple_mesh_bind_group_layout = Some(bind_group_layout);
624 }
625
626 pub fn curve_network_edge_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
628 self.curve_network_edge_bind_group_layout
629 .as_ref()
630 .expect("curve network edge pipeline not initialized")
631 }
632
633 pub(crate) fn create_curve_network_edge_pipeline(&mut self) {
635 let shader_source = include_str!("../../shaders/curve_network_edge.wgsl");
636 let shader = self
637 .device
638 .create_shader_module(wgpu::ShaderModuleDescriptor {
639 label: Some("curve network edge shader"),
640 source: wgpu::ShaderSource::Wgsl(shader_source.into()),
641 });
642
643 let bind_group_layout =
644 self.device
645 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
646 label: Some("curve network edge bind group layout"),
647 entries: &[
648 wgpu::BindGroupLayoutEntry {
650 binding: 0,
651 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
652 ty: wgpu::BindingType::Buffer {
653 ty: wgpu::BufferBindingType::Uniform,
654 has_dynamic_offset: false,
655 min_binding_size: NonZeroU64::new(272),
656 },
657 count: None,
658 },
659 wgpu::BindGroupLayoutEntry {
661 binding: 1,
662 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
663 ty: wgpu::BindingType::Buffer {
664 ty: wgpu::BufferBindingType::Uniform,
665 has_dynamic_offset: false,
666 min_binding_size: NonZeroU64::new(32),
667 },
668 count: None,
669 },
670 wgpu::BindGroupLayoutEntry {
672 binding: 2,
673 visibility: wgpu::ShaderStages::VERTEX,
674 ty: wgpu::BindingType::Buffer {
675 ty: wgpu::BufferBindingType::Storage { read_only: true },
676 has_dynamic_offset: false,
677 min_binding_size: None,
678 },
679 count: None,
680 },
681 wgpu::BindGroupLayoutEntry {
683 binding: 3,
684 visibility: wgpu::ShaderStages::VERTEX,
685 ty: wgpu::BindingType::Buffer {
686 ty: wgpu::BufferBindingType::Storage { read_only: true },
687 has_dynamic_offset: false,
688 min_binding_size: None,
689 },
690 count: None,
691 },
692 wgpu::BindGroupLayoutEntry {
694 binding: 4,
695 visibility: wgpu::ShaderStages::VERTEX,
696 ty: wgpu::BindingType::Buffer {
697 ty: wgpu::BufferBindingType::Storage { read_only: true },
698 has_dynamic_offset: false,
699 min_binding_size: None,
700 },
701 count: None,
702 },
703 wgpu::BindGroupLayoutEntry {
705 binding: 5,
706 visibility: wgpu::ShaderStages::VERTEX,
707 ty: wgpu::BindingType::Buffer {
708 ty: wgpu::BufferBindingType::Storage { read_only: true },
709 has_dynamic_offset: false,
710 min_binding_size: None,
711 },
712 count: None,
713 },
714 ],
715 });
716
717 let pipeline_layout = self
718 .device
719 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
720 label: Some("curve network edge pipeline layout"),
721 bind_group_layouts: &[
722 &bind_group_layout,
723 &self.slice_plane_bind_group_layout,
724 &self.matcap_bind_group_layout,
725 ],
726 push_constant_ranges: &[],
727 });
728
729 let pipeline = self
730 .device
731 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
732 label: Some("curve network edge pipeline"),
733 layout: Some(&pipeline_layout),
734 vertex: wgpu::VertexState {
735 module: &shader,
736 entry_point: Some("vs_main"),
737 buffers: &[],
738 compilation_options: wgpu::PipelineCompilationOptions::default(),
739 },
740 fragment: Some(wgpu::FragmentState {
741 module: &shader,
742 entry_point: Some("fs_main"),
743 targets: &[Some(wgpu::ColorTargetState {
744 format: wgpu::TextureFormat::Rgba16Float, blend: Some(wgpu::BlendState::REPLACE),
746 write_mask: wgpu::ColorWrites::ALL,
747 })],
748 compilation_options: wgpu::PipelineCompilationOptions::default(),
749 }),
750 primitive: wgpu::PrimitiveState {
751 topology: wgpu::PrimitiveTopology::LineList,
752 strip_index_format: None,
753 front_face: wgpu::FrontFace::Ccw,
754 cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill,
756 unclipped_depth: false,
757 conservative: false,
758 },
759 depth_stencil: Some(wgpu::DepthStencilState {
760 format: wgpu::TextureFormat::Depth24PlusStencil8,
761 depth_write_enabled: true,
762 depth_compare: wgpu::CompareFunction::Less,
763 stencil: wgpu::StencilState::default(),
764 bias: wgpu::DepthBiasState::default(),
765 }),
766 multisample: wgpu::MultisampleState::default(),
767 multiview: None,
768 cache: None,
769 });
770
771 self.curve_network_edge_pipeline = Some(pipeline);
772 self.curve_network_edge_bind_group_layout = Some(bind_group_layout);
773 }
774
775 pub(crate) fn create_curve_network_tube_pipelines(&mut self) {
777 let compute_shader_source = include_str!("../../shaders/curve_network_tube_compute.wgsl");
779 let compute_shader = self
780 .device
781 .create_shader_module(wgpu::ShaderModuleDescriptor {
782 label: Some("Curve Network Tube Compute Shader"),
783 source: wgpu::ShaderSource::Wgsl(compute_shader_source.into()),
784 });
785
786 let compute_bind_group_layout =
788 self.device
789 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
790 label: Some("Curve Network Tube Compute Bind Group Layout"),
791 entries: &[
792 wgpu::BindGroupLayoutEntry {
794 binding: 0,
795 visibility: wgpu::ShaderStages::COMPUTE,
796 ty: wgpu::BindingType::Buffer {
797 ty: wgpu::BufferBindingType::Storage { read_only: true },
798 has_dynamic_offset: false,
799 min_binding_size: None,
800 },
801 count: None,
802 },
803 wgpu::BindGroupLayoutEntry {
805 binding: 1,
806 visibility: wgpu::ShaderStages::COMPUTE,
807 ty: wgpu::BindingType::Buffer {
808 ty: wgpu::BufferBindingType::Uniform,
809 has_dynamic_offset: false,
810 min_binding_size: NonZeroU64::new(32),
811 },
812 count: None,
813 },
814 wgpu::BindGroupLayoutEntry {
816 binding: 2,
817 visibility: wgpu::ShaderStages::COMPUTE,
818 ty: wgpu::BindingType::Buffer {
819 ty: wgpu::BufferBindingType::Storage { read_only: false },
820 has_dynamic_offset: false,
821 min_binding_size: None,
822 },
823 count: None,
824 },
825 wgpu::BindGroupLayoutEntry {
827 binding: 3,
828 visibility: wgpu::ShaderStages::COMPUTE,
829 ty: wgpu::BindingType::Buffer {
830 ty: wgpu::BufferBindingType::Uniform,
831 has_dynamic_offset: false,
832 min_binding_size: NonZeroU64::new(4),
833 },
834 count: None,
835 },
836 ],
837 });
838
839 let compute_pipeline_layout =
840 self.device
841 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
842 label: Some("Curve Network Tube Compute Pipeline Layout"),
843 bind_group_layouts: &[&compute_bind_group_layout],
844 push_constant_ranges: &[],
845 });
846
847 let compute_pipeline =
848 self.device
849 .create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
850 label: Some("Curve Network Tube Compute Pipeline"),
851 layout: Some(&compute_pipeline_layout),
852 module: &compute_shader,
853 entry_point: Some("main"),
854 compilation_options: wgpu::PipelineCompilationOptions::default(),
855 cache: None,
856 });
857
858 let render_shader_source = include_str!("../../shaders/curve_network_tube.wgsl");
860 let render_shader = self
861 .device
862 .create_shader_module(wgpu::ShaderModuleDescriptor {
863 label: Some("Curve Network Tube Render Shader"),
864 source: wgpu::ShaderSource::Wgsl(render_shader_source.into()),
865 });
866
867 let render_bind_group_layout =
869 self.device
870 .create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
871 label: Some("Curve Network Tube Render Bind Group Layout"),
872 entries: &[
873 wgpu::BindGroupLayoutEntry {
875 binding: 0,
876 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
877 ty: wgpu::BindingType::Buffer {
878 ty: wgpu::BufferBindingType::Uniform,
879 has_dynamic_offset: false,
880 min_binding_size: NonZeroU64::new(272),
881 },
882 count: None,
883 },
884 wgpu::BindGroupLayoutEntry {
886 binding: 1,
887 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
888 ty: wgpu::BindingType::Buffer {
889 ty: wgpu::BufferBindingType::Uniform,
890 has_dynamic_offset: false,
891 min_binding_size: NonZeroU64::new(32),
892 },
893 count: None,
894 },
895 wgpu::BindGroupLayoutEntry {
897 binding: 2,
898 visibility: wgpu::ShaderStages::FRAGMENT,
899 ty: wgpu::BindingType::Buffer {
900 ty: wgpu::BufferBindingType::Storage { read_only: true },
901 has_dynamic_offset: false,
902 min_binding_size: None,
903 },
904 count: None,
905 },
906 wgpu::BindGroupLayoutEntry {
908 binding: 3,
909 visibility: wgpu::ShaderStages::FRAGMENT,
910 ty: wgpu::BindingType::Buffer {
911 ty: wgpu::BufferBindingType::Storage { read_only: true },
912 has_dynamic_offset: false,
913 min_binding_size: None,
914 },
915 count: None,
916 },
917 ],
918 });
919
920 let render_pipeline_layout =
921 self.device
922 .create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
923 label: Some("Curve Network Tube Render Pipeline Layout"),
924 bind_group_layouts: &[
925 &render_bind_group_layout,
926 &self.slice_plane_bind_group_layout,
927 &self.matcap_bind_group_layout,
928 ],
929 push_constant_ranges: &[],
930 });
931
932 let render_pipeline = self
933 .device
934 .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
935 label: Some("Curve Network Tube Render Pipeline"),
936 layout: Some(&render_pipeline_layout),
937 vertex: wgpu::VertexState {
938 module: &render_shader,
939 entry_point: Some("vs_main"),
940 buffers: &[
941 wgpu::VertexBufferLayout {
943 array_stride: 32, step_mode: wgpu::VertexStepMode::Vertex,
945 attributes: &[
946 wgpu::VertexAttribute {
947 format: wgpu::VertexFormat::Float32x4,
948 offset: 0,
949 shader_location: 0,
950 },
951 wgpu::VertexAttribute {
952 format: wgpu::VertexFormat::Uint32x4,
953 offset: 16,
954 shader_location: 1,
955 },
956 ],
957 },
958 ],
959 compilation_options: wgpu::PipelineCompilationOptions::default(),
960 },
961 fragment: Some(wgpu::FragmentState {
962 module: &render_shader,
963 entry_point: Some("fs_main"),
964 targets: &[Some(wgpu::ColorTargetState {
965 format: wgpu::TextureFormat::Rgba16Float,
966 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
967 write_mask: wgpu::ColorWrites::ALL,
968 })],
969 compilation_options: wgpu::PipelineCompilationOptions::default(),
970 }),
971 primitive: wgpu::PrimitiveState {
972 topology: wgpu::PrimitiveTopology::TriangleList,
973 strip_index_format: None,
974 front_face: wgpu::FrontFace::Ccw,
975 cull_mode: None, polygon_mode: wgpu::PolygonMode::Fill,
977 unclipped_depth: false,
978 conservative: false,
979 },
980 depth_stencil: Some(wgpu::DepthStencilState {
981 format: wgpu::TextureFormat::Depth24PlusStencil8,
982 depth_write_enabled: true,
983 depth_compare: wgpu::CompareFunction::Less,
984 stencil: wgpu::StencilState::default(),
985 bias: wgpu::DepthBiasState::default(),
986 }),
987 multisample: wgpu::MultisampleState::default(),
988 multiview: None,
989 cache: None,
990 });
991
992 self.curve_network_tube_pipeline = Some(render_pipeline);
993 self.curve_network_tube_compute_pipeline = Some(compute_pipeline);
994 self.curve_network_tube_bind_group_layout = Some(render_bind_group_layout);
995 self.curve_network_tube_compute_bind_group_layout = Some(compute_bind_group_layout);
996 }
997
998 pub fn curve_network_tube_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
1000 self.curve_network_tube_bind_group_layout
1001 .as_ref()
1002 .expect("Tube bind group layout not initialized")
1003 }
1004
1005 pub fn curve_network_tube_compute_bind_group_layout(&self) -> &wgpu::BindGroupLayout {
1007 self.curve_network_tube_compute_bind_group_layout
1008 .as_ref()
1009 .expect("Tube compute bind group layout not initialized")
1010 }
1011
1012 pub fn curve_network_tube_compute_pipeline(&self) -> &wgpu::ComputePipeline {
1014 self.curve_network_tube_compute_pipeline
1015 .as_ref()
1016 .expect("Tube compute pipeline not initialized")
1017 }
1018}