1use super::*;
2
3impl DeviceResources {
4 pub fn new(
9 device: &wgpu::Device,
10 target_format: wgpu::TextureFormat,
11 sample_count: u32,
12 ) -> Self {
13 Self::new_with_cache(device, target_format, sample_count, None)
14 }
15
16 pub fn new_with_cache(
25 device: &wgpu::Device,
26 target_format: wgpu::TextureFormat,
27 sample_count: u32,
28 pipeline_cache_data: Option<&[u8]>,
29 ) -> Self {
30 use wgpu;
31
32 let pipeline_cache = if device.features().contains(wgpu::Features::PIPELINE_CACHE) {
38 Some(unsafe {
39 device.create_pipeline_cache(&wgpu::PipelineCacheDescriptor {
40 label: Some("viewport_pipeline_cache"),
41 data: pipeline_cache_data,
42 fallback: true,
43 })
44 })
45 } else {
46 None
47 };
48
49 let init_start = std::time::Instant::now();
55 let mut init_ckpt = init_start;
56 let mut mark = |section: &str| {
57 let now = std::time::Instant::now();
58 tracing::info!(
59 target: "viewport_lib::init",
60 section,
61 ms = now.duration_since(init_ckpt).as_secs_f32() * 1000.0,
62 "gpu resources init phase"
63 );
64 init_ckpt = now;
65 };
66
67 let deform_enabled = device.limits().max_bind_groups >= 3;
75
76 let mesh_src = if deform_enabled {
77 include_str!(concat!(env!("OUT_DIR"), "/mesh.wgsl"))
78 } else {
79 include_str!(concat!(env!("OUT_DIR"), "/mesh_noop.wgsl"))
80 };
81 let shader = crate::resources::builders::wgsl_module(device, "mesh_shader", mesh_src);
82
83 let camera_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
87 label: Some("camera_bgl"),
88 entries: &[
89 wgpu::BindGroupLayoutEntry {
90 binding: 0,
91 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
92 ty: wgpu::BindingType::Buffer {
93 ty: wgpu::BufferBindingType::Uniform,
94 has_dynamic_offset: false,
95 min_binding_size: None,
96 },
97 count: None,
98 },
99 wgpu::BindGroupLayoutEntry {
100 binding: 1,
101 visibility: wgpu::ShaderStages::FRAGMENT,
102 ty: wgpu::BindingType::Texture {
103 sample_type: wgpu::TextureSampleType::Depth,
104 view_dimension: wgpu::TextureViewDimension::D2,
105 multisampled: false,
106 },
107 count: None,
108 },
109 wgpu::BindGroupLayoutEntry {
110 binding: 2,
111 visibility: wgpu::ShaderStages::FRAGMENT,
112 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Comparison),
113 count: None,
114 },
115 wgpu::BindGroupLayoutEntry {
116 binding: 3,
117 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
118 ty: wgpu::BindingType::Buffer {
119 ty: wgpu::BufferBindingType::Uniform,
120 has_dynamic_offset: false,
121 min_binding_size: None,
122 },
123 count: None,
124 },
125 wgpu::BindGroupLayoutEntry {
127 binding: 4,
128 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
129 ty: wgpu::BindingType::Buffer {
130 ty: wgpu::BufferBindingType::Uniform,
131 has_dynamic_offset: false,
132 min_binding_size: None,
133 },
134 count: None,
135 },
136 wgpu::BindGroupLayoutEntry {
138 binding: 5,
139 visibility: wgpu::ShaderStages::FRAGMENT,
140 ty: wgpu::BindingType::Buffer {
141 ty: wgpu::BufferBindingType::Uniform,
142 has_dynamic_offset: false,
143 min_binding_size: None,
144 },
145 count: None,
146 },
147 wgpu::BindGroupLayoutEntry {
149 binding: 6,
150 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
151 ty: wgpu::BindingType::Buffer {
152 ty: wgpu::BufferBindingType::Uniform,
153 has_dynamic_offset: false,
154 min_binding_size: None,
155 },
156 count: None,
157 },
158 wgpu::BindGroupLayoutEntry {
160 binding: 7,
161 visibility: wgpu::ShaderStages::FRAGMENT,
162 ty: wgpu::BindingType::Texture {
163 sample_type: wgpu::TextureSampleType::Float { filterable: true },
164 view_dimension: wgpu::TextureViewDimension::D2,
165 multisampled: false,
166 },
167 count: None,
168 },
169 wgpu::BindGroupLayoutEntry {
171 binding: 8,
172 visibility: wgpu::ShaderStages::FRAGMENT,
173 ty: wgpu::BindingType::Texture {
174 sample_type: wgpu::TextureSampleType::Float { filterable: true },
175 view_dimension: wgpu::TextureViewDimension::D2,
176 multisampled: false,
177 },
178 count: None,
179 },
180 wgpu::BindGroupLayoutEntry {
182 binding: 9,
183 visibility: wgpu::ShaderStages::FRAGMENT,
184 ty: wgpu::BindingType::Texture {
185 sample_type: wgpu::TextureSampleType::Float { filterable: true },
186 view_dimension: wgpu::TextureViewDimension::D2,
187 multisampled: false,
188 },
189 count: None,
190 },
191 wgpu::BindGroupLayoutEntry {
193 binding: 10,
194 visibility: wgpu::ShaderStages::FRAGMENT,
195 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
196 count: None,
197 },
198 wgpu::BindGroupLayoutEntry {
200 binding: 11,
201 visibility: wgpu::ShaderStages::FRAGMENT,
202 ty: wgpu::BindingType::Texture {
203 sample_type: wgpu::TextureSampleType::Float { filterable: true },
204 view_dimension: wgpu::TextureViewDimension::D2,
205 multisampled: false,
206 },
207 count: None,
208 },
209 wgpu::BindGroupLayoutEntry {
213 binding: 12,
214 visibility: wgpu::ShaderStages::FRAGMENT,
215 ty: wgpu::BindingType::Buffer {
216 ty: wgpu::BufferBindingType::Storage { read_only: false },
217 has_dynamic_offset: false,
218 min_binding_size: None,
219 },
220 count: None,
221 },
222 wgpu::BindGroupLayoutEntry {
226 binding: 13,
227 visibility: wgpu::ShaderStages::FRAGMENT,
228 ty: wgpu::BindingType::Buffer {
229 ty: wgpu::BufferBindingType::Storage { read_only: true },
230 has_dynamic_offset: false,
231 min_binding_size: None,
232 },
233 count: None,
234 },
235 wgpu::BindGroupLayoutEntry {
238 binding: 14,
239 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
240 ty: wgpu::BindingType::Buffer {
241 ty: wgpu::BufferBindingType::Uniform,
242 has_dynamic_offset: false,
243 min_binding_size: None,
244 },
245 count: None,
246 },
247 wgpu::BindGroupLayoutEntry {
250 binding: 15,
251 visibility: wgpu::ShaderStages::FRAGMENT,
252 ty: wgpu::BindingType::Buffer {
253 ty: wgpu::BufferBindingType::Storage { read_only: true },
254 has_dynamic_offset: false,
255 min_binding_size: None,
256 },
257 count: None,
258 },
259 wgpu::BindGroupLayoutEntry {
262 binding: 16,
263 visibility: wgpu::ShaderStages::FRAGMENT,
264 ty: wgpu::BindingType::Buffer {
265 ty: wgpu::BufferBindingType::Storage { read_only: true },
266 has_dynamic_offset: false,
267 min_binding_size: None,
268 },
269 count: None,
270 },
271 wgpu::BindGroupLayoutEntry {
276 binding: 17,
277 visibility: wgpu::ShaderStages::FRAGMENT,
278 ty: wgpu::BindingType::Texture {
279 sample_type: wgpu::TextureSampleType::Depth,
280 view_dimension: if cfg!(target_os = "ios") {
281 wgpu::TextureViewDimension::D2Array
282 } else {
283 wgpu::TextureViewDimension::CubeArray
284 },
285 multisampled: false,
286 },
287 count: None,
288 },
289 ],
290 });
291
292 let object_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
303 label: Some("object_bgl"),
304 entries: &[
305 wgpu::BindGroupLayoutEntry {
307 binding: 0,
308 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
309 ty: wgpu::BindingType::Buffer {
310 ty: wgpu::BufferBindingType::Uniform,
311 has_dynamic_offset: false,
312 min_binding_size: None,
313 },
314 count: None,
315 },
316 wgpu::BindGroupLayoutEntry {
318 binding: 1,
319 visibility: wgpu::ShaderStages::FRAGMENT,
320 ty: wgpu::BindingType::Texture {
321 sample_type: wgpu::TextureSampleType::Float { filterable: true },
322 view_dimension: wgpu::TextureViewDimension::D2,
323 multisampled: false,
324 },
325 count: None,
326 },
327 wgpu::BindGroupLayoutEntry {
329 binding: 2,
330 visibility: wgpu::ShaderStages::FRAGMENT,
331 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
332 count: None,
333 },
334 wgpu::BindGroupLayoutEntry {
336 binding: 3,
337 visibility: wgpu::ShaderStages::FRAGMENT,
338 ty: wgpu::BindingType::Texture {
339 sample_type: wgpu::TextureSampleType::Float { filterable: true },
340 view_dimension: wgpu::TextureViewDimension::D2,
341 multisampled: false,
342 },
343 count: None,
344 },
345 wgpu::BindGroupLayoutEntry {
347 binding: 4,
348 visibility: wgpu::ShaderStages::FRAGMENT,
349 ty: wgpu::BindingType::Texture {
350 sample_type: wgpu::TextureSampleType::Float { filterable: true },
351 view_dimension: wgpu::TextureViewDimension::D2,
352 multisampled: false,
353 },
354 count: None,
355 },
356 wgpu::BindGroupLayoutEntry {
358 binding: 5,
359 visibility: wgpu::ShaderStages::FRAGMENT,
360 ty: wgpu::BindingType::Texture {
361 sample_type: wgpu::TextureSampleType::Float { filterable: true },
362 view_dimension: wgpu::TextureViewDimension::D2,
363 multisampled: false,
364 },
365 count: None,
366 },
367 wgpu::BindGroupLayoutEntry {
369 binding: 6,
370 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
371 ty: wgpu::BindingType::Buffer {
372 ty: wgpu::BufferBindingType::Storage { read_only: true },
373 has_dynamic_offset: false,
374 min_binding_size: None,
375 },
376 count: None,
377 },
378 wgpu::BindGroupLayoutEntry {
380 binding: 7,
381 visibility: wgpu::ShaderStages::FRAGMENT,
382 ty: wgpu::BindingType::Texture {
383 sample_type: wgpu::TextureSampleType::Float { filterable: true },
384 view_dimension: wgpu::TextureViewDimension::D2,
385 multisampled: false,
386 },
387 count: None,
388 },
389 wgpu::BindGroupLayoutEntry {
391 binding: 8,
392 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
393 ty: wgpu::BindingType::Buffer {
394 ty: wgpu::BufferBindingType::Storage { read_only: true },
395 has_dynamic_offset: false,
396 min_binding_size: None,
397 },
398 count: None,
399 },
400 wgpu::BindGroupLayoutEntry {
402 binding: 9,
403 visibility: wgpu::ShaderStages::VERTEX,
404 ty: wgpu::BindingType::Buffer {
405 ty: wgpu::BufferBindingType::Storage { read_only: true },
406 has_dynamic_offset: false,
407 min_binding_size: None,
408 },
409 count: None,
410 },
411 wgpu::BindGroupLayoutEntry {
413 binding: 10,
414 visibility: wgpu::ShaderStages::FRAGMENT,
415 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
416 count: None,
417 },
418 wgpu::BindGroupLayoutEntry {
420 binding: 11,
421 visibility: wgpu::ShaderStages::FRAGMENT,
422 ty: wgpu::BindingType::Texture {
423 sample_type: wgpu::TextureSampleType::Float { filterable: true },
424 view_dimension: wgpu::TextureViewDimension::D2,
425 multisampled: false,
426 },
427 count: None,
428 },
429 wgpu::BindGroupLayoutEntry {
431 binding: 12,
432 visibility: wgpu::ShaderStages::FRAGMENT,
433 ty: wgpu::BindingType::Texture {
434 sample_type: wgpu::TextureSampleType::Float { filterable: true },
435 view_dimension: wgpu::TextureViewDimension::D2,
436 multisampled: false,
437 },
438 count: None,
439 },
440 wgpu::BindGroupLayoutEntry {
443 binding: 13,
444 visibility: wgpu::ShaderStages::VERTEX,
445 ty: wgpu::BindingType::Buffer {
446 ty: wgpu::BufferBindingType::Storage { read_only: true },
447 has_dynamic_offset: false,
448 min_binding_size: None,
449 },
450 count: None,
451 },
452 wgpu::BindGroupLayoutEntry {
454 binding: 14,
455 visibility: wgpu::ShaderStages::VERTEX,
456 ty: wgpu::BindingType::Buffer {
457 ty: wgpu::BufferBindingType::Storage { read_only: true },
458 has_dynamic_offset: false,
459 min_binding_size: None,
460 },
461 count: None,
462 },
463 ],
464 });
465
466 let texture_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
471 label: Some("texture_bgl"),
472 entries: &[
473 wgpu::BindGroupLayoutEntry {
475 binding: 0,
476 visibility: wgpu::ShaderStages::FRAGMENT,
477 ty: wgpu::BindingType::Texture {
478 sample_type: wgpu::TextureSampleType::Float { filterable: true },
479 view_dimension: wgpu::TextureViewDimension::D2,
480 multisampled: false,
481 },
482 count: None,
483 },
484 wgpu::BindGroupLayoutEntry {
486 binding: 1,
487 visibility: wgpu::ShaderStages::FRAGMENT,
488 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
489 count: None,
490 },
491 wgpu::BindGroupLayoutEntry {
493 binding: 2,
494 visibility: wgpu::ShaderStages::FRAGMENT,
495 ty: wgpu::BindingType::Texture {
496 sample_type: wgpu::TextureSampleType::Float { filterable: true },
497 view_dimension: wgpu::TextureViewDimension::D2,
498 multisampled: false,
499 },
500 count: None,
501 },
502 wgpu::BindGroupLayoutEntry {
504 binding: 3,
505 visibility: wgpu::ShaderStages::FRAGMENT,
506 ty: wgpu::BindingType::Texture {
507 sample_type: wgpu::TextureSampleType::Float { filterable: true },
508 view_dimension: wgpu::TextureViewDimension::D2,
509 multisampled: false,
510 },
511 count: None,
512 },
513 ],
514 });
515
516 mark("shaders_and_bind_group_layouts");
517
518 let deform = if deform_enabled {
523 crate::resources::mesh_sidecar::deform::DeformationState::new(device)
524 } else {
525 crate::resources::mesh_sidecar::deform::DeformationState::new_disabled(device)
526 };
527 let deform_bgl = deform.enabled.then_some(&deform.bind_group_layout);
528
529 let pipeline_layout = crate::resources::mesh::mesh_pipelines::mesh_pipeline_layout(
534 device,
535 "mesh_pipeline_layout",
536 &camera_bgl,
537 &object_bgl,
538 deform_bgl,
539 );
540
541 let ldr = crate::resources::mesh::mesh_pipelines::build_ldr_mesh_pipelines(
547 device,
548 &pipeline_layout,
549 &shader,
550 target_format,
551 sample_count,
552 pipeline_cache.as_ref(),
553 );
554 let solid_pipeline = ldr.solid;
555 let solid_two_sided_pipeline = ldr.solid_two_sided;
556 let transparent_pipeline = ldr.transparent;
557 let wireframe_pipeline = ldr.wireframe;
558
559 mark("mesh_pipelines");
560
561 let camera_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
565 label: Some("camera_uniform_buf"),
566 size: std::mem::size_of::<CameraUniform>() as u64,
567 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
568 mapped_at_creation: false,
569 });
570
571 let light_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
572 label: Some("light_uniform_buf"),
573 size: std::mem::size_of::<LightUniform>() as u64,
574 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
575 mapped_at_creation: false,
576 });
577
578 let light_storage_buf = device.create_buffer(&wgpu::BufferDescriptor {
579 label: Some("light_storage_buf"),
580 size: (std::mem::size_of::<crate::resources::SingleLightUniform>()
581 * crate::resources::MAX_SCENE_LIGHTS) as u64,
582 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
583 mapped_at_creation: false,
584 });
585
586 let clip_planes_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
589 label: Some("clip_planes_uniform_buf"),
590 size: std::mem::size_of::<ClipPlanesUniform>() as u64,
591 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
592 mapped_at_creation: false,
593 });
594
595 let clip_volume_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
598 label: Some("clip_volume_uniform_buf"),
599 size: std::mem::size_of::<ClipVolumesUniform>() as u64,
600 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
601 mapped_at_creation: false,
602 });
603
604 let shadow_map_texture = device.create_texture(&wgpu::TextureDescriptor {
608 label: Some("shadow_atlas"),
609 size: wgpu::Extent3d {
610 width: SHADOW_ATLAS_SIZE,
611 height: SHADOW_ATLAS_SIZE,
612 depth_or_array_layers: 1,
613 },
614 mip_level_count: 1,
615 sample_count: 1,
616 dimension: wgpu::TextureDimension::D2,
617 format: wgpu::TextureFormat::Depth32Float,
618 usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
619 view_formats: &[],
620 });
621 let shadow_map_view =
622 shadow_map_texture.create_view(&wgpu::TextureViewDescriptor::default());
623
624 let shadow_sampler = device.create_sampler(&wgpu::SamplerDescriptor {
625 label: Some("shadow_sampler"),
626 compare: Some(wgpu::CompareFunction::LessEqual),
627 mag_filter: wgpu::FilterMode::Linear,
628 min_filter: wgpu::FilterMode::Linear,
629 ..Default::default()
630 });
631
632 let point_shadow_face_size = crate::renderer::POINT_SHADOW_FACE_SIZE;
641 let point_shadow_max_lights = crate::renderer::MAX_POINT_SHADOW_LIGHTS;
642 let point_shadow_layers = point_shadow_max_lights * 6;
643 let point_shadow_cube_texture = device.create_texture(&wgpu::TextureDescriptor {
644 label: Some("point_shadow_cube_array"),
645 size: wgpu::Extent3d {
646 width: point_shadow_face_size,
647 height: point_shadow_face_size,
648 depth_or_array_layers: point_shadow_layers,
649 },
650 mip_level_count: 1,
651 sample_count: 1,
652 dimension: wgpu::TextureDimension::D2,
653 format: wgpu::TextureFormat::Depth32Float,
654 usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
655 view_formats: &[],
656 });
657 let point_shadow_cube_view =
658 point_shadow_cube_texture.create_view(&wgpu::TextureViewDescriptor {
659 label: Some("point_shadow_cube_view"),
660 dimension: Some(if cfg!(target_os = "ios") {
663 wgpu::TextureViewDimension::D2Array
664 } else {
665 wgpu::TextureViewDimension::CubeArray
666 }),
667 aspect: wgpu::TextureAspect::DepthOnly,
668 base_array_layer: 0,
669 array_layer_count: Some(point_shadow_layers),
670 base_mip_level: 0,
671 mip_level_count: Some(1),
672 format: Some(wgpu::TextureFormat::Depth32Float),
673 usage: None,
674 });
675 let point_shadow_face_views: Vec<wgpu::TextureView> = (0..point_shadow_layers)
676 .map(|layer| {
677 point_shadow_cube_texture.create_view(&wgpu::TextureViewDescriptor {
678 label: Some("point_shadow_face_view"),
679 dimension: Some(wgpu::TextureViewDimension::D2),
680 aspect: wgpu::TextureAspect::DepthOnly,
681 base_array_layer: layer,
682 array_layer_count: Some(1),
683 base_mip_level: 0,
684 mip_level_count: Some(1),
685 format: Some(wgpu::TextureFormat::Depth32Float),
686 usage: None,
687 })
688 })
689 .collect();
690
691 mark("buffers_and_shadow_textures");
695
696 let shadow_atlas_depth_sampler =
698 crate::resources::builders::clamp_nearest_sampler(device, "shadow_atlas_depth_sampler");
699
700 let shadow_info_buf = device.create_buffer(&wgpu::BufferDescriptor {
702 label: Some("shadow_info_buf"),
703 size: std::mem::size_of::<ShadowAtlasUniform>() as u64,
704 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
705 mapped_at_creation: false,
706 });
707
708 let ibl_fallback_texture = device.create_texture(&wgpu::TextureDescriptor {
714 label: Some("ibl_fallback_black"),
715 size: wgpu::Extent3d {
716 width: 1,
717 height: 1,
718 depth_or_array_layers: 1,
719 },
720 mip_level_count: 1,
721 sample_count: 1,
722 dimension: wgpu::TextureDimension::D2,
723 format: wgpu::TextureFormat::Rgba16Float,
724 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
725 view_formats: &[],
726 });
727 let ibl_fallback_view =
728 ibl_fallback_texture.create_view(&wgpu::TextureViewDescriptor::default());
729
730 let ibl_fallback_brdf_texture = device.create_texture(&wgpu::TextureDescriptor {
735 label: Some("ibl_fallback_brdf"),
736 size: wgpu::Extent3d {
737 width: 1,
738 height: 1,
739 depth_or_array_layers: 1,
740 },
741 mip_level_count: 1,
742 sample_count: 1,
743 dimension: wgpu::TextureDimension::D2,
744 format: wgpu::TextureFormat::Rgba16Float,
745 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
746 view_formats: &[],
747 });
748 let ibl_fallback_brdf_view =
749 ibl_fallback_brdf_texture.create_view(&wgpu::TextureViewDescriptor::default());
750
751 let ibl_sampler = crate::resources::builders::env_sampler(device, "ibl_sampler");
752
753 let debug_frag_sentinel_buf = device.create_buffer(&wgpu::BufferDescriptor {
755 label: Some("debug_frag_sentinel_buf"),
756 size: 16,
757 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC,
758 mapped_at_creation: false,
759 });
760
761 let clustered = crate::resources::gpu::clustered::ClusteredResources::new(device);
762
763 mark("clustered");
764
765 let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
766 label: Some("camera_bind_group"),
767 layout: &camera_bgl,
768 entries: &[
769 wgpu::BindGroupEntry {
770 binding: 0,
771 resource: camera_uniform_buf.as_entire_binding(),
772 },
773 wgpu::BindGroupEntry {
774 binding: 1,
775 resource: wgpu::BindingResource::TextureView(&shadow_map_view),
776 },
777 wgpu::BindGroupEntry {
778 binding: 2,
779 resource: wgpu::BindingResource::Sampler(&shadow_sampler),
780 },
781 wgpu::BindGroupEntry {
782 binding: 3,
783 resource: light_uniform_buf.as_entire_binding(),
784 },
785 wgpu::BindGroupEntry {
786 binding: 4,
787 resource: clip_planes_uniform_buf.as_entire_binding(),
788 },
789 wgpu::BindGroupEntry {
790 binding: 5,
791 resource: shadow_info_buf.as_entire_binding(),
792 },
793 wgpu::BindGroupEntry {
794 binding: 6,
795 resource: clip_volume_uniform_buf.as_entire_binding(),
796 },
797 wgpu::BindGroupEntry {
799 binding: 7,
800 resource: wgpu::BindingResource::TextureView(&ibl_fallback_view),
801 },
802 wgpu::BindGroupEntry {
803 binding: 8,
804 resource: wgpu::BindingResource::TextureView(&ibl_fallback_view),
805 },
806 wgpu::BindGroupEntry {
807 binding: 9,
808 resource: wgpu::BindingResource::TextureView(&ibl_fallback_brdf_view),
809 },
810 wgpu::BindGroupEntry {
811 binding: 10,
812 resource: wgpu::BindingResource::Sampler(&ibl_sampler),
813 },
814 wgpu::BindGroupEntry {
815 binding: 11,
816 resource: wgpu::BindingResource::TextureView(&ibl_fallback_view),
817 },
818 wgpu::BindGroupEntry {
819 binding: 12,
820 resource: debug_frag_sentinel_buf.as_entire_binding(),
821 },
822 wgpu::BindGroupEntry {
823 binding: 13,
824 resource: light_storage_buf.as_entire_binding(),
825 },
826 wgpu::BindGroupEntry {
827 binding: 14,
828 resource: clustered.grid_uniform_buf.as_entire_binding(),
829 },
830 wgpu::BindGroupEntry {
831 binding: 15,
832 resource: clustered.cluster_grid_buf.as_entire_binding(),
833 },
834 wgpu::BindGroupEntry {
835 binding: 16,
836 resource: clustered.light_index_buf.as_entire_binding(),
837 },
838 wgpu::BindGroupEntry {
839 binding: 17,
840 resource: wgpu::BindingResource::TextureView(&point_shadow_cube_view),
841 },
842 ],
843 });
844
845 let shadow_src = if deform_enabled {
849 include_str!(concat!(env!("OUT_DIR"), "/shadow.wgsl"))
850 } else {
851 include_str!(concat!(env!("OUT_DIR"), "/shadow_noop.wgsl"))
852 };
853 let shadow_shader =
854 crate::resources::builders::wgsl_module(device, "shadow_shader", shadow_src);
855
856 let shadow_camera_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
858 label: Some("shadow_camera_bgl"),
859 entries: &[wgpu::BindGroupLayoutEntry {
860 binding: 0,
861 visibility: wgpu::ShaderStages::VERTEX,
862 ty: wgpu::BindingType::Buffer {
863 ty: wgpu::BufferBindingType::Uniform,
864 has_dynamic_offset: true,
868 min_binding_size: None,
869 },
870 count: None,
871 }],
872 });
873
874 let shadow_pl_bgls: Vec<&wgpu::BindGroupLayout> = if let Some(d) = deform_bgl {
875 vec![&shadow_camera_bgl, &object_bgl, d]
876 } else {
877 vec![&shadow_camera_bgl, &object_bgl]
878 };
879 let shadow_pipeline_layout =
880 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
881 label: Some("shadow_pipeline_layout"),
882 bind_group_layouts: &shadow_pl_bgls,
883 push_constant_ranges: &[],
884 });
885
886 let shadow_pipeline = crate::resources::mesh::mesh_pipelines::build_shadow_pipeline(
895 device,
896 &shadow_pipeline_layout,
897 &shadow_shader,
898 Some(wgpu::Face::Front),
899 pipeline_cache.as_ref(),
900 );
901 let shadow_pipeline_two_sided =
902 crate::resources::mesh::mesh_pipelines::build_shadow_pipeline(
903 device,
904 &shadow_pipeline_layout,
905 &shadow_shader,
906 None,
907 pipeline_cache.as_ref(),
908 );
909
910 const SHADOW_SLOT_STRIDE: u64 = 256;
913 let shadow_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
914 label: Some("shadow_uniform_buf"),
915 size: 4 * SHADOW_SLOT_STRIDE,
916 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
917 mapped_at_creation: false,
918 });
919
920 let shadow_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
921 label: Some("shadow_bind_group"),
922 layout: &shadow_camera_bgl,
923 entries: &[wgpu::BindGroupEntry {
924 binding: 0,
925 resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
927 buffer: &shadow_uniform_buf,
928 offset: 0,
929 size: Some(
930 wgpu::BufferSize::new(std::mem::size_of::<[[f32; 4]; 4]>() as u64).unwrap(),
931 ),
932 }),
933 }],
934 });
935
936 let shadow_point_src = if deform_enabled {
945 include_str!(concat!(env!("OUT_DIR"), "/shadow_point.wgsl"))
946 } else {
947 include_str!(concat!(env!("OUT_DIR"), "/shadow_point_noop.wgsl"))
948 };
949 let shadow_point_shader = crate::resources::builders::wgsl_module(
950 device,
951 "shadow_point_shader",
952 shadow_point_src,
953 );
954 let shadow_point_face_bgl =
955 device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
956 label: Some("shadow_point_face_bgl"),
957 entries: &[wgpu::BindGroupLayoutEntry {
958 binding: 0,
959 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
960 ty: wgpu::BindingType::Buffer {
961 ty: wgpu::BufferBindingType::Uniform,
962 has_dynamic_offset: true,
963 min_binding_size: None,
964 },
965 count: None,
966 }],
967 });
968 let shadow_point_pl_bgls: Vec<&wgpu::BindGroupLayout> = if let Some(d) = deform_bgl {
969 vec![&shadow_point_face_bgl, &object_bgl, d]
970 } else {
971 vec![&shadow_point_face_bgl, &object_bgl]
972 };
973 let shadow_point_pipeline_layout =
974 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
975 label: Some("shadow_point_pipeline_layout"),
976 bind_group_layouts: &shadow_point_pl_bgls,
977 push_constant_ranges: &[],
978 });
979 let shadow_point_pipeline =
980 crate::resources::mesh::mesh_pipelines::build_shadow_point_pipeline(
981 device,
982 &shadow_point_pipeline_layout,
983 &shadow_point_shader,
984 pipeline_cache.as_ref(),
985 );
986
987 const SHADOW_POINT_FACE_STRIDE: u64 = 256;
990 let shadow_point_face_count = (point_shadow_max_lights * 6) as u64;
991 let shadow_point_face_buf = device.create_buffer(&wgpu::BufferDescriptor {
992 label: Some("shadow_point_face_buf"),
993 size: shadow_point_face_count * SHADOW_POINT_FACE_STRIDE,
994 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
995 mapped_at_creation: false,
996 });
997 let shadow_point_face_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
998 label: Some("shadow_point_face_bind_group"),
999 layout: &shadow_point_face_bgl,
1000 entries: &[wgpu::BindGroupEntry {
1001 binding: 0,
1002 resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
1003 buffer: &shadow_point_face_buf,
1004 offset: 0,
1005 size: Some(wgpu::BufferSize::new(96).unwrap()),
1008 }),
1009 }],
1010 });
1011
1012 mark("shadow_pipelines");
1013
1014 let gizmo_shader = crate::resources::builders::wgsl_module(
1018 device,
1019 "gizmo_shader",
1020 crate::resources::builders::wgsl_source!("gizmo"),
1021 );
1022
1023 let gizmo_bgl = crate::resources::builders::uniform_bgl(
1027 device,
1028 "gizmo_bgl",
1029 wgpu::ShaderStages::VERTEX,
1030 );
1031
1032 let gizmo_pipeline_layout =
1036 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1037 label: Some("gizmo_pipeline_layout"),
1038 bind_group_layouts: &[&camera_bgl, &gizmo_bgl],
1039 push_constant_ranges: &[],
1040 });
1041
1042 let gizmo_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1048 label: Some("gizmo_pipeline"),
1049 layout: Some(&gizmo_pipeline_layout),
1050 vertex: wgpu::VertexState {
1051 module: &gizmo_shader,
1052 entry_point: Some("vs_main"),
1053 buffers: &[Vertex::buffer_layout()],
1054 compilation_options: wgpu::PipelineCompilationOptions::default(),
1055 },
1056 fragment: Some(wgpu::FragmentState {
1057 module: &gizmo_shader,
1058 entry_point: Some("fs_main"),
1059 targets: &[Some(wgpu::ColorTargetState {
1060 format: target_format,
1061 blend: None,
1062 write_mask: wgpu::ColorWrites::ALL,
1063 })],
1064 compilation_options: wgpu::PipelineCompilationOptions::default(),
1065 }),
1066 primitive: wgpu::PrimitiveState {
1067 topology: wgpu::PrimitiveTopology::TriangleList,
1068 strip_index_format: None,
1069 front_face: wgpu::FrontFace::Ccw,
1070 cull_mode: None, unclipped_depth: false,
1072 polygon_mode: wgpu::PolygonMode::Fill,
1073 conservative: false,
1074 },
1075 depth_stencil: Some(wgpu::DepthStencilState {
1076 format: wgpu::TextureFormat::Depth24PlusStencil8,
1077 depth_write_enabled: false,
1078 depth_compare: wgpu::CompareFunction::Always, stencil: wgpu::StencilState::default(),
1080 bias: wgpu::DepthBiasState::default(),
1081 }),
1082 multisample: wgpu::MultisampleState {
1083 count: sample_count,
1084 mask: !0,
1085 alpha_to_coverage_enabled: false,
1086 },
1087 multiview: None,
1088 cache: pipeline_cache.as_ref(),
1089 });
1090
1091 let (gizmo_verts, gizmo_indices) =
1095 crate::interaction::manipulation::gizmo::build_gizmo_mesh(
1096 crate::interaction::manipulation::gizmo::GizmoMode::Translate,
1097 crate::interaction::manipulation::gizmo::GizmoAxis::None,
1098 glam::Quat::IDENTITY,
1099 );
1100
1101 let gizmo_vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
1102 label: Some("gizmo_vertex_buf"),
1103 size: (std::mem::size_of::<Vertex>() * gizmo_verts.len().max(1)) as u64,
1104 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
1105 mapped_at_creation: true,
1106 });
1107 gizmo_vertex_buffer
1108 .slice(..)
1109 .get_mapped_range_mut()
1110 .copy_from_slice(bytemuck::cast_slice(&gizmo_verts));
1111 gizmo_vertex_buffer.unmap();
1112
1113 let gizmo_index_count = gizmo_indices.len() as u32;
1114 let gizmo_index_buffer = device.create_buffer(&wgpu::BufferDescriptor {
1115 label: Some("gizmo_index_buf"),
1116 size: (std::mem::size_of::<u32>() * gizmo_indices.len().max(1)) as u64,
1117 usage: wgpu::BufferUsages::INDEX | wgpu::BufferUsages::COPY_DST,
1118 mapped_at_creation: true,
1119 });
1120 gizmo_index_buffer
1121 .slice(..)
1122 .get_mapped_range_mut()
1123 .copy_from_slice(bytemuck::cast_slice(&gizmo_indices));
1124 gizmo_index_buffer.unmap();
1125
1126 let gizmo_uniform = crate::interaction::manipulation::gizmo::GizmoUniform {
1130 model: glam::Mat4::IDENTITY.to_cols_array_2d(),
1131 };
1132 let gizmo_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
1133 label: Some("gizmo_uniform_buf"),
1134 size: std::mem::size_of::<crate::interaction::manipulation::gizmo::GizmoUniform>()
1135 as u64,
1136 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
1137 mapped_at_creation: true,
1138 });
1139 gizmo_uniform_buf
1140 .slice(..)
1141 .get_mapped_range_mut()
1142 .copy_from_slice(bytemuck::cast_slice(&[gizmo_uniform]));
1143 gizmo_uniform_buf.unmap();
1144
1145 let gizmo_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1146 label: Some("gizmo_bind_group"),
1147 layout: &gizmo_bgl,
1148 entries: &[wgpu::BindGroupEntry {
1149 binding: 0,
1150 resource: gizmo_uniform_buf.as_entire_binding(),
1151 }],
1152 });
1153
1154 let overlay_shader = crate::resources::builders::wgsl_module(
1158 device,
1159 "overlay_shader",
1160 crate::resources::builders::wgsl_source!("overlay"),
1161 );
1162
1163 let overlay_bgl = crate::resources::builders::uniform_bgl(
1167 device,
1168 "overlay_bgl",
1169 wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
1170 );
1171
1172 let overlay_pipeline_layout =
1176 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1177 label: Some("overlay_pipeline_layout"),
1178 bind_group_layouts: &[&camera_bgl, &overlay_bgl],
1179 push_constant_ranges: &[],
1180 });
1181
1182 let overlay_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1190 label: Some("overlay_pipeline"),
1191 layout: Some(&overlay_pipeline_layout),
1192 vertex: wgpu::VertexState {
1193 module: &overlay_shader,
1194 entry_point: Some("vs_main"),
1195 buffers: &[OverlayVertex::buffer_layout()],
1196 compilation_options: wgpu::PipelineCompilationOptions::default(),
1197 },
1198 fragment: Some(wgpu::FragmentState {
1199 module: &overlay_shader,
1200 entry_point: Some("fs_main"),
1201 targets: &[Some(wgpu::ColorTargetState {
1202 format: target_format,
1203 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
1204 write_mask: wgpu::ColorWrites::ALL,
1205 })],
1206 compilation_options: wgpu::PipelineCompilationOptions::default(),
1207 }),
1208 primitive: wgpu::PrimitiveState {
1209 topology: wgpu::PrimitiveTopology::TriangleList,
1210 strip_index_format: None,
1211 front_face: wgpu::FrontFace::Ccw,
1212 cull_mode: None, unclipped_depth: false,
1214 polygon_mode: wgpu::PolygonMode::Fill,
1215 conservative: false,
1216 },
1217 depth_stencil: Some(wgpu::DepthStencilState {
1218 format: wgpu::TextureFormat::Depth24PlusStencil8,
1219 depth_write_enabled: false, depth_compare: wgpu::CompareFunction::Less,
1221 stencil: wgpu::StencilState::default(),
1222 bias: wgpu::DepthBiasState::default(),
1223 }),
1224 multisample: wgpu::MultisampleState {
1225 count: sample_count,
1226 mask: !0,
1227 alpha_to_coverage_enabled: false,
1228 },
1229 multiview: None,
1230 cache: pipeline_cache.as_ref(),
1231 });
1232
1233 let overlay_line_pipeline =
1240 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1241 label: Some("overlay_line_pipeline"),
1242 layout: Some(&overlay_pipeline_layout),
1243 vertex: wgpu::VertexState {
1244 module: &overlay_shader,
1245 entry_point: Some("vs_main"),
1246 buffers: &[OverlayVertex::buffer_layout()],
1247 compilation_options: wgpu::PipelineCompilationOptions::default(),
1248 },
1249 fragment: Some(wgpu::FragmentState {
1250 module: &overlay_shader,
1251 entry_point: Some("fs_main"),
1252 targets: &[Some(wgpu::ColorTargetState {
1253 format: target_format,
1254 blend: None,
1255 write_mask: wgpu::ColorWrites::ALL,
1256 })],
1257 compilation_options: wgpu::PipelineCompilationOptions::default(),
1258 }),
1259 primitive: wgpu::PrimitiveState {
1260 topology: wgpu::PrimitiveTopology::LineList,
1261 strip_index_format: None,
1262 front_face: wgpu::FrontFace::Ccw,
1263 cull_mode: None,
1264 unclipped_depth: false,
1265 polygon_mode: wgpu::PolygonMode::Fill,
1266 conservative: false,
1267 },
1268 depth_stencil: Some(wgpu::DepthStencilState {
1269 format: wgpu::TextureFormat::Depth24PlusStencil8,
1270 depth_write_enabled: false,
1271 depth_compare: wgpu::CompareFunction::Less,
1272 stencil: wgpu::StencilState::default(),
1273 bias: wgpu::DepthBiasState::default(),
1274 }),
1275 multisample: wgpu::MultisampleState {
1276 count: sample_count,
1277 mask: !0,
1278 alpha_to_coverage_enabled: false,
1279 },
1280 multiview: None,
1281 cache: pipeline_cache.as_ref(),
1282 });
1283
1284 let grid_shader = crate::resources::builders::wgsl_module(
1294 device,
1295 "grid_shader",
1296 crate::resources::builders::wgsl_source!("grid"),
1297 );
1298 let grid_bgl = crate::resources::builders::uniform_bgl(
1299 device,
1300 "grid_bgl",
1301 wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
1302 );
1303 let grid_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1304 label: Some("grid_pipeline_layout"),
1305 bind_group_layouts: &[&grid_bgl],
1306 push_constant_ranges: &[],
1307 });
1308 let grid_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1309 label: Some("grid_pipeline"),
1310 layout: Some(&grid_pipeline_layout),
1311 vertex: wgpu::VertexState {
1312 module: &grid_shader,
1313 entry_point: Some("vs_main"),
1314 buffers: &[], compilation_options: wgpu::PipelineCompilationOptions::default(),
1316 },
1317 fragment: Some(wgpu::FragmentState {
1318 module: &grid_shader,
1319 entry_point: Some("fs_main"),
1320 targets: &[Some(wgpu::ColorTargetState {
1321 format: target_format,
1322 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
1323 write_mask: wgpu::ColorWrites::ALL,
1324 })],
1325 compilation_options: wgpu::PipelineCompilationOptions::default(),
1326 }),
1327 primitive: wgpu::PrimitiveState {
1328 topology: wgpu::PrimitiveTopology::TriangleList,
1329 ..Default::default()
1330 },
1331 depth_stencil: Some(wgpu::DepthStencilState {
1332 format: wgpu::TextureFormat::Depth24PlusStencil8,
1333 depth_write_enabled: true,
1334 depth_compare: wgpu::CompareFunction::LessEqual,
1335 stencil: wgpu::StencilState::default(),
1336 bias: wgpu::DepthBiasState {
1337 constant: 4,
1342 slope_scale: 0.0,
1343 clamp: 0.0,
1344 },
1345 }),
1346 multisample: wgpu::MultisampleState {
1347 count: sample_count,
1348 mask: !0,
1349 alpha_to_coverage_enabled: false,
1350 },
1351 multiview: None,
1352 cache: pipeline_cache.as_ref(),
1353 });
1354 let grid_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
1356 label: Some("grid_uniform_buf"),
1357 size: std::mem::size_of::<GridUniform>() as u64,
1358 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
1359 mapped_at_creation: false,
1360 });
1361 let grid_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1362 label: Some("grid_bind_group"),
1363 layout: &grid_bgl,
1364 entries: &[wgpu::BindGroupEntry {
1365 binding: 0,
1366 resource: grid_uniform_buf.as_entire_binding(),
1367 }],
1368 });
1369
1370 let ground_plane_shader = crate::resources::builders::wgsl_module(
1379 device,
1380 "ground_plane_shader",
1381 crate::resources::builders::wgsl_source!("ground_plane"),
1382 );
1383 let ground_plane_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
1384 label: Some("ground_plane_bgl"),
1385 entries: &[
1386 wgpu::BindGroupLayoutEntry {
1388 binding: 0,
1389 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
1390 ty: wgpu::BindingType::Buffer {
1391 ty: wgpu::BufferBindingType::Uniform,
1392 has_dynamic_offset: false,
1393 min_binding_size: None,
1394 },
1395 count: None,
1396 },
1397 wgpu::BindGroupLayoutEntry {
1399 binding: 1,
1400 visibility: wgpu::ShaderStages::FRAGMENT,
1401 ty: wgpu::BindingType::Texture {
1402 sample_type: wgpu::TextureSampleType::Depth,
1403 view_dimension: wgpu::TextureViewDimension::D2,
1404 multisampled: false,
1405 },
1406 count: None,
1407 },
1408 wgpu::BindGroupLayoutEntry {
1410 binding: 2,
1411 visibility: wgpu::ShaderStages::FRAGMENT,
1412 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Comparison),
1413 count: None,
1414 },
1415 wgpu::BindGroupLayoutEntry {
1417 binding: 3,
1418 visibility: wgpu::ShaderStages::FRAGMENT,
1419 ty: wgpu::BindingType::Buffer {
1420 ty: wgpu::BufferBindingType::Uniform,
1421 has_dynamic_offset: false,
1422 min_binding_size: None,
1423 },
1424 count: None,
1425 },
1426 ],
1427 });
1428 let ground_plane_pipeline_layout =
1429 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1430 label: Some("ground_plane_pipeline_layout"),
1431 bind_group_layouts: &[&ground_plane_bgl],
1432 push_constant_ranges: &[],
1433 });
1434 let ground_plane_pipeline =
1435 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1436 label: Some("ground_plane_pipeline"),
1437 layout: Some(&ground_plane_pipeline_layout),
1438 vertex: wgpu::VertexState {
1439 module: &ground_plane_shader,
1440 entry_point: Some("vs_main"),
1441 buffers: &[],
1442 compilation_options: wgpu::PipelineCompilationOptions::default(),
1443 },
1444 fragment: Some(wgpu::FragmentState {
1445 module: &ground_plane_shader,
1446 entry_point: Some("fs_main"),
1447 targets: &[Some(wgpu::ColorTargetState {
1448 format: target_format,
1449 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
1450 write_mask: wgpu::ColorWrites::ALL,
1451 })],
1452 compilation_options: wgpu::PipelineCompilationOptions::default(),
1453 }),
1454 primitive: wgpu::PrimitiveState {
1455 topology: wgpu::PrimitiveTopology::TriangleList,
1456 cull_mode: None,
1457 ..Default::default()
1458 },
1459 depth_stencil: Some(wgpu::DepthStencilState {
1460 format: wgpu::TextureFormat::Depth24PlusStencil8,
1461 depth_write_enabled: true,
1462 depth_compare: wgpu::CompareFunction::LessEqual,
1463 stencil: wgpu::StencilState::default(),
1464 bias: wgpu::DepthBiasState::default(),
1465 }),
1466 multisample: wgpu::MultisampleState {
1467 count: sample_count,
1468 mask: !0,
1469 alpha_to_coverage_enabled: false,
1470 },
1471 multiview: None,
1472 cache: pipeline_cache.as_ref(),
1473 });
1474 let ground_plane_uniform_buf = device.create_buffer(&wgpu::BufferDescriptor {
1475 label: Some("ground_plane_uniform_buf"),
1476 size: std::mem::size_of::<GroundPlaneUniform>() as u64,
1477 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
1478 mapped_at_creation: false,
1479 });
1480 let ground_plane_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1481 label: Some("ground_plane_bind_group"),
1482 layout: &ground_plane_bgl,
1483 entries: &[
1484 wgpu::BindGroupEntry {
1485 binding: 0,
1486 resource: ground_plane_uniform_buf.as_entire_binding(),
1487 },
1488 wgpu::BindGroupEntry {
1489 binding: 1,
1490 resource: wgpu::BindingResource::TextureView(&shadow_map_view),
1491 },
1492 wgpu::BindGroupEntry {
1493 binding: 2,
1494 resource: wgpu::BindingResource::Sampler(&shadow_sampler),
1495 },
1496 wgpu::BindGroupEntry {
1497 binding: 3,
1498 resource: shadow_info_buf.as_entire_binding(),
1499 },
1500 ],
1501 });
1502
1503 let atlas_blit_shader = crate::resources::builders::wgsl_module(
1507 device,
1508 "shadow_atlas_blit",
1509 crate::resources::builders::wgsl_source!("shadow_atlas_blit"),
1510 );
1511 let atlas_blit_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
1512 label: Some("atlas_blit_bgl"),
1513 entries: &[
1514 wgpu::BindGroupLayoutEntry {
1515 binding: 0,
1516 visibility: wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
1517 ty: wgpu::BindingType::Buffer {
1518 ty: wgpu::BufferBindingType::Uniform,
1519 has_dynamic_offset: false,
1520 min_binding_size: None,
1521 },
1522 count: None,
1523 },
1524 wgpu::BindGroupLayoutEntry {
1525 binding: 1,
1526 visibility: wgpu::ShaderStages::FRAGMENT,
1527 ty: wgpu::BindingType::Texture {
1528 sample_type: wgpu::TextureSampleType::Depth,
1529 view_dimension: wgpu::TextureViewDimension::D2,
1530 multisampled: false,
1531 },
1532 count: None,
1533 },
1534 wgpu::BindGroupLayoutEntry {
1535 binding: 2,
1536 visibility: wgpu::ShaderStages::FRAGMENT,
1537 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::NonFiltering),
1538 count: None,
1539 },
1540 ],
1541 });
1542 let atlas_blit_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1543 label: Some("atlas_blit_layout"),
1544 bind_group_layouts: &[&atlas_blit_bgl],
1545 push_constant_ranges: &[],
1546 });
1547 let shadow_atlas_viewer_buf = device.create_buffer(&wgpu::BufferDescriptor {
1548 label: Some("shadow_atlas_viewer_buf"),
1549 size: std::mem::size_of::<AtlasBlitUniform>() as u64,
1550 usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
1551 mapped_at_creation: false,
1552 });
1553 let shadow_atlas_viewer_bg = device.create_bind_group(&wgpu::BindGroupDescriptor {
1554 label: Some("shadow_atlas_viewer_bg"),
1555 layout: &atlas_blit_bgl,
1556 entries: &[
1557 wgpu::BindGroupEntry {
1558 binding: 0,
1559 resource: shadow_atlas_viewer_buf.as_entire_binding(),
1560 },
1561 wgpu::BindGroupEntry {
1562 binding: 1,
1563 resource: wgpu::BindingResource::TextureView(&shadow_map_view),
1564 },
1565 wgpu::BindGroupEntry {
1566 binding: 2,
1567 resource: wgpu::BindingResource::Sampler(&shadow_atlas_depth_sampler),
1568 },
1569 ],
1570 });
1571 let shadow_atlas_viewer_pipeline =
1572 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1573 label: Some("shadow_atlas_viewer_pipeline"),
1574 layout: Some(&atlas_blit_layout),
1575 vertex: wgpu::VertexState {
1576 module: &atlas_blit_shader,
1577 entry_point: Some("vs_main"),
1578 buffers: &[],
1579 compilation_options: wgpu::PipelineCompilationOptions::default(),
1580 },
1581 fragment: Some(wgpu::FragmentState {
1582 module: &atlas_blit_shader,
1583 entry_point: Some("fs_main"),
1584 targets: &[Some(wgpu::ColorTargetState {
1585 format: target_format,
1586 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
1587 write_mask: wgpu::ColorWrites::ALL,
1588 })],
1589 compilation_options: wgpu::PipelineCompilationOptions::default(),
1590 }),
1591 primitive: wgpu::PrimitiveState {
1592 topology: wgpu::PrimitiveTopology::TriangleList,
1593 cull_mode: None,
1594 ..Default::default()
1595 },
1596 depth_stencil: Some(wgpu::DepthStencilState {
1597 format: wgpu::TextureFormat::Depth24PlusStencil8,
1598 depth_write_enabled: false,
1599 depth_compare: wgpu::CompareFunction::Always,
1600 stencil: wgpu::StencilState::default(),
1601 bias: wgpu::DepthBiasState::default(),
1602 }),
1603 multisample: wgpu::MultisampleState {
1604 count: sample_count,
1605 mask: !0,
1606 alpha_to_coverage_enabled: false,
1607 },
1608 multiview: None,
1609 cache: pipeline_cache.as_ref(),
1610 });
1611
1612 let axes_shader = crate::resources::builders::wgsl_module(
1616 device,
1617 "axes_overlay_shader",
1618 crate::resources::builders::wgsl_source!("axes_overlay"),
1619 );
1620
1621 let axes_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1622 label: Some("axes_pipeline_layout"),
1623 bind_group_layouts: &[],
1624 push_constant_ranges: &[],
1625 });
1626
1627 let axes_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
1628 label: Some("axes_pipeline"),
1629 layout: Some(&axes_pipeline_layout),
1630 vertex: wgpu::VertexState {
1631 module: &axes_shader,
1632 entry_point: Some("vs_main"),
1633 buffers: &[
1634 crate::interaction::widgets::axes_indicator::AxesVertex::buffer_layout(),
1635 ],
1636 compilation_options: wgpu::PipelineCompilationOptions::default(),
1637 },
1638 fragment: Some(wgpu::FragmentState {
1639 module: &axes_shader,
1640 entry_point: Some("fs_main"),
1641 targets: &[Some(wgpu::ColorTargetState {
1642 format: target_format,
1643 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
1644 write_mask: wgpu::ColorWrites::ALL,
1645 })],
1646 compilation_options: wgpu::PipelineCompilationOptions::default(),
1647 }),
1648 primitive: wgpu::PrimitiveState {
1649 topology: wgpu::PrimitiveTopology::TriangleList,
1650 strip_index_format: None,
1651 front_face: wgpu::FrontFace::Ccw,
1652 cull_mode: None,
1653 unclipped_depth: false,
1654 polygon_mode: wgpu::PolygonMode::Fill,
1655 conservative: false,
1656 },
1657 depth_stencil: Some(wgpu::DepthStencilState {
1658 format: wgpu::TextureFormat::Depth24PlusStencil8,
1659 depth_write_enabled: false,
1660 depth_compare: wgpu::CompareFunction::Always,
1661 stencil: wgpu::StencilState::default(),
1662 bias: wgpu::DepthBiasState::default(),
1663 }),
1664 multisample: wgpu::MultisampleState {
1665 count: sample_count,
1666 mask: !0,
1667 alpha_to_coverage_enabled: false,
1668 },
1669 multiview: None,
1670 cache: pipeline_cache.as_ref(),
1671 });
1672
1673 let axes_vertex_buffer = device.create_buffer(&wgpu::BufferDescriptor {
1675 label: Some("axes_vertex_buf"),
1676 size: (std::mem::size_of::<crate::interaction::widgets::axes_indicator::AxesVertex>()
1677 * 2048) as u64,
1678 usage: wgpu::BufferUsages::VERTEX | wgpu::BufferUsages::COPY_DST,
1679 mapped_at_creation: false,
1680 });
1681
1682 mark("ui_pipelines");
1683
1684 let material_sampler = crate::resources::builders::repeat_linear_sampler(
1688 device,
1689 "material_sampler",
1690 wgpu::FilterMode::Nearest,
1691 );
1692
1693 let lut_sampler = crate::resources::builders::clamp_linear_sampler(device, "lut_sampler");
1695
1696 let fallback_normal_map = device.create_texture(&wgpu::TextureDescriptor {
1700 label: Some("fallback_normal_map"),
1701 size: wgpu::Extent3d {
1702 width: 1,
1703 height: 1,
1704 depth_or_array_layers: 1,
1705 },
1706 mip_level_count: 1,
1707 sample_count: 1,
1708 dimension: wgpu::TextureDimension::D2,
1709 format: wgpu::TextureFormat::Rgba8Unorm,
1710 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1711 view_formats: &[],
1712 });
1713 let fallback_normal_map_view =
1714 fallback_normal_map.create_view(&wgpu::TextureViewDescriptor::default());
1715
1716 let fallback_ao_map = device.create_texture(&wgpu::TextureDescriptor {
1720 label: Some("fallback_ao_map"),
1721 size: wgpu::Extent3d {
1722 width: 1,
1723 height: 1,
1724 depth_or_array_layers: 1,
1725 },
1726 mip_level_count: 1,
1727 sample_count: 1,
1728 dimension: wgpu::TextureDimension::D2,
1729 format: wgpu::TextureFormat::Rgba8Unorm,
1730 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1731 view_formats: &[],
1732 });
1733 let fallback_ao_map_view =
1734 fallback_ao_map.create_view(&wgpu::TextureViewDescriptor::default());
1735
1736 let fallback_metallic_roughness_texture = device.create_texture(&wgpu::TextureDescriptor {
1741 label: Some("fallback_metallic_roughness_texture"),
1742 size: wgpu::Extent3d {
1743 width: 1,
1744 height: 1,
1745 depth_or_array_layers: 1,
1746 },
1747 mip_level_count: 1,
1748 sample_count: 1,
1749 dimension: wgpu::TextureDimension::D2,
1750 format: wgpu::TextureFormat::Rgba8Unorm,
1751 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1752 view_formats: &[],
1753 });
1754 let fallback_metallic_roughness_texture_view = fallback_metallic_roughness_texture
1755 .create_view(&wgpu::TextureViewDescriptor::default());
1756
1757 let fallback_emissive_texture = device.create_texture(&wgpu::TextureDescriptor {
1762 label: Some("fallback_emissive_texture"),
1763 size: wgpu::Extent3d {
1764 width: 1,
1765 height: 1,
1766 depth_or_array_layers: 1,
1767 },
1768 mip_level_count: 1,
1769 sample_count: 1,
1770 dimension: wgpu::TextureDimension::D2,
1771 format: wgpu::TextureFormat::Rgba8Unorm,
1772 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1773 view_formats: &[],
1774 });
1775 let fallback_emissive_texture_view =
1776 fallback_emissive_texture.create_view(&wgpu::TextureViewDescriptor::default());
1777
1778 let fallback_texture = {
1782 let tex = device.create_texture(&wgpu::TextureDescriptor {
1783 label: Some("fallback_texture"),
1784 size: wgpu::Extent3d {
1785 width: 1,
1786 height: 1,
1787 depth_or_array_layers: 1,
1788 },
1789 mip_level_count: 1,
1790 sample_count: 1,
1791 dimension: wgpu::TextureDimension::D2,
1792 format: wgpu::TextureFormat::Rgba8UnormSrgb,
1793 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1794 view_formats: &[],
1795 });
1796 let view = tex.create_view(&wgpu::TextureViewDescriptor::default());
1798 let sampler = material_sampler.clone();
1800 let bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
1801 label: Some("fallback_texture_bg"),
1802 layout: &texture_bgl,
1803 entries: &[
1804 wgpu::BindGroupEntry {
1805 binding: 0,
1806 resource: wgpu::BindingResource::TextureView(&view),
1807 },
1808 wgpu::BindGroupEntry {
1809 binding: 1,
1810 resource: wgpu::BindingResource::Sampler(&sampler),
1811 },
1812 wgpu::BindGroupEntry {
1813 binding: 2,
1814 resource: wgpu::BindingResource::TextureView(&fallback_normal_map_view),
1815 },
1816 wgpu::BindGroupEntry {
1817 binding: 3,
1818 resource: wgpu::BindingResource::TextureView(&fallback_ao_map_view),
1819 },
1820 ],
1821 });
1822 GpuTexture {
1823 texture: tex,
1824 view,
1825 sampler,
1826 bind_group,
1827 }
1828 };
1829
1830 let fallback_lut_texture = device.create_texture(&wgpu::TextureDescriptor {
1834 label: Some("fallback_lut_texture"),
1835 size: wgpu::Extent3d {
1836 width: 1,
1837 height: 1,
1838 depth_or_array_layers: 1,
1839 },
1840 mip_level_count: 1,
1841 sample_count: 1,
1842 dimension: wgpu::TextureDimension::D2,
1843 format: wgpu::TextureFormat::Rgba8Unorm,
1844 usage: wgpu::TextureUsages::TEXTURE_BINDING | wgpu::TextureUsages::COPY_DST,
1845 view_formats: &[],
1846 });
1847 let fallback_lut_view =
1851 fallback_lut_texture.create_view(&wgpu::TextureViewDescriptor::default());
1852
1853 let fallback_scalar_buf = device.create_buffer(&wgpu::BufferDescriptor {
1854 label: Some("fallback_scalar_buf"),
1855 size: 4,
1856 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
1857 mapped_at_creation: true,
1858 });
1859 {
1860 let mut view = fallback_scalar_buf.slice(..).get_mapped_range_mut();
1861 view.copy_from_slice(&[0u8; 4]);
1862 }
1863 fallback_scalar_buf.unmap();
1864
1865 let fallback_face_colour_buf = device.create_buffer(&wgpu::BufferDescriptor {
1866 label: Some("fallback_face_colour_buf"),
1867 size: 16, usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
1869 mapped_at_creation: true,
1870 });
1871 {
1872 let mut view = fallback_face_colour_buf.slice(..).get_mapped_range_mut();
1873 view.copy_from_slice(&[0u8; 16]);
1874 }
1875 fallback_face_colour_buf.unmap();
1876
1877 let fallback_warp_buf = device.create_buffer(&wgpu::BufferDescriptor {
1878 label: Some("fallback_warp_buf"),
1879 size: 12, usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
1881 mapped_at_creation: true,
1882 });
1883 {
1884 let mut view = fallback_warp_buf.slice(..).get_mapped_range_mut();
1885 view.copy_from_slice(&[0u8; 12]);
1886 }
1887 fallback_warp_buf.unmap();
1888
1889 let fallback_position_override_buf = device.create_buffer(&wgpu::BufferDescriptor {
1890 label: Some("fallback_position_override_buf"),
1891 size: 12, usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
1893 mapped_at_creation: true,
1894 });
1895 {
1896 let mut view = fallback_position_override_buf
1897 .slice(..)
1898 .get_mapped_range_mut();
1899 view.copy_from_slice(&[0u8; 12]);
1900 }
1901 fallback_position_override_buf.unmap();
1902
1903 let fallback_normal_override_buf = device.create_buffer(&wgpu::BufferDescriptor {
1904 label: Some("fallback_normal_override_buf"),
1905 size: 12,
1906 usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_DST,
1907 mapped_at_creation: true,
1908 });
1909 {
1910 let mut view = fallback_normal_override_buf
1911 .slice(..)
1912 .get_mapped_range_mut();
1913 view.copy_from_slice(&[0u8; 12]);
1914 }
1915 fallback_normal_override_buf.unmap();
1916
1917 let (cube_verts, cube_indices) = build_unit_cube();
1923 let cube_mesh = Self::create_mesh(
1924 device,
1925 &object_bgl,
1926 &fallback_texture.view,
1927 &fallback_normal_map_view,
1928 &fallback_ao_map_view,
1929 &fallback_texture.sampler,
1930 &lut_sampler,
1931 &fallback_lut_view,
1932 &fallback_scalar_buf,
1933 &fallback_texture.view,
1934 &fallback_face_colour_buf,
1935 &fallback_warp_buf,
1936 &fallback_position_override_buf,
1937 &fallback_normal_override_buf,
1938 &fallback_metallic_roughness_texture_view,
1939 &fallback_emissive_texture_view,
1940 &cube_verts,
1941 &cube_indices,
1942 );
1943
1944 let outline_bgl = crate::resources::builders::uniform_bgl(
1950 device,
1951 "outline_bgl",
1952 wgpu::ShaderStages::VERTEX | wgpu::ShaderStages::FRAGMENT,
1953 );
1954
1955 let xray_shader = crate::resources::builders::wgsl_module(
1956 device,
1957 "xray_shader",
1958 crate::resources::builders::wgsl_source!("xray"),
1959 );
1960
1961 let outline_pl_bgls: Vec<&wgpu::BindGroupLayout> = if let Some(d) = deform_bgl {
1962 vec![&camera_bgl, &outline_bgl, d]
1963 } else {
1964 vec![&camera_bgl, &outline_bgl]
1965 };
1966 let outline_pipeline_layout =
1967 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
1968 label: Some("outline_pipeline_layout"),
1969 bind_group_layouts: &outline_pl_bgls,
1970 push_constant_ranges: &[],
1971 });
1972
1973 let outline_mask_src = if deform_enabled {
1976 include_str!(concat!(env!("OUT_DIR"), "/outline_mask.wgsl"))
1977 } else {
1978 include_str!(concat!(env!("OUT_DIR"), "/outline_mask_noop.wgsl"))
1979 };
1980 let outline_mask_shader = crate::resources::builders::wgsl_module(
1981 device,
1982 "outline_mask_shader",
1983 outline_mask_src,
1984 );
1985 let outline_masks = crate::resources::mesh::mesh_pipelines::build_outline_mask_pipelines(
1986 device,
1987 &outline_pipeline_layout,
1988 &outline_mask_shader,
1989 wgpu::TextureFormat::R8Unorm,
1990 pipeline_cache.as_ref(),
1991 );
1992 let outline_mask_pipeline = outline_masks.mask;
1993 let outline_mask_two_sided_pipeline = outline_masks.mask_two_sided;
1994
1995 let splat_outline_mask_shader = crate::resources::builders::wgsl_module(
1999 device,
2000 "splat_outline_mask_shader",
2001 crate::resources::builders::wgsl_source!("splat_outline_mask"),
2002 );
2003 let splat_outline_pos_attrs = [wgpu::VertexAttribute {
2004 offset: 0,
2005 shader_location: 0,
2006 format: wgpu::VertexFormat::Float32x3,
2007 }];
2008 let splat_outline_pos_layout = wgpu::VertexBufferLayout {
2009 array_stride: 12, step_mode: wgpu::VertexStepMode::Instance,
2011 attributes: &splat_outline_pos_attrs,
2012 };
2013 let splat_outline_size_attrs = [wgpu::VertexAttribute {
2014 offset: 0,
2015 shader_location: 1,
2016 format: wgpu::VertexFormat::Float32,
2017 }];
2018 let splat_outline_size_layout = wgpu::VertexBufferLayout {
2019 array_stride: 4, step_mode: wgpu::VertexStepMode::Instance,
2021 attributes: &splat_outline_size_attrs,
2022 };
2023 let splat_outline_mask_pipeline =
2024 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
2025 label: Some("splat_outline_mask_pipeline"),
2026 layout: Some(&outline_pipeline_layout),
2027 vertex: wgpu::VertexState {
2028 module: &splat_outline_mask_shader,
2029 entry_point: Some("vs_main"),
2030 buffers: &[splat_outline_pos_layout, splat_outline_size_layout],
2031 compilation_options: wgpu::PipelineCompilationOptions::default(),
2032 },
2033 fragment: Some(wgpu::FragmentState {
2034 module: &splat_outline_mask_shader,
2035 entry_point: Some("fs_main"),
2036 targets: &[Some(wgpu::ColorTargetState {
2037 format: wgpu::TextureFormat::R8Unorm,
2038 blend: None,
2039 write_mask: wgpu::ColorWrites::ALL,
2040 })],
2041 compilation_options: wgpu::PipelineCompilationOptions::default(),
2042 }),
2043 primitive: wgpu::PrimitiveState {
2044 topology: wgpu::PrimitiveTopology::TriangleList,
2045 cull_mode: None,
2046 ..Default::default()
2047 },
2048 depth_stencil: Some(wgpu::DepthStencilState {
2049 format: wgpu::TextureFormat::Depth24PlusStencil8,
2050 depth_write_enabled: false,
2051 depth_compare: wgpu::CompareFunction::Less,
2052 stencil: wgpu::StencilState::default(),
2053 bias: wgpu::DepthBiasState::default(),
2054 }),
2055 multisample: wgpu::MultisampleState {
2056 count: 1,
2057 mask: !0,
2058 alpha_to_coverage_enabled: false,
2059 },
2060 multiview: None,
2061 cache: pipeline_cache.as_ref(),
2062 });
2063
2064 let outline_edge_shader = crate::resources::builders::wgsl_module(
2067 device,
2068 "outline_edge_shader",
2069 crate::resources::builders::wgsl_source!("outline_edge"),
2070 );
2071 let outline_edge_bgl = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
2072 label: Some("outline_edge_bgl"),
2073 entries: &[
2074 wgpu::BindGroupLayoutEntry {
2075 binding: 0,
2076 visibility: wgpu::ShaderStages::FRAGMENT,
2077 ty: wgpu::BindingType::Texture {
2078 sample_type: wgpu::TextureSampleType::Float { filterable: true },
2079 view_dimension: wgpu::TextureViewDimension::D2,
2080 multisampled: false,
2081 },
2082 count: None,
2083 },
2084 wgpu::BindGroupLayoutEntry {
2085 binding: 1,
2086 visibility: wgpu::ShaderStages::FRAGMENT,
2087 ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
2088 count: None,
2089 },
2090 wgpu::BindGroupLayoutEntry {
2091 binding: 2,
2092 visibility: wgpu::ShaderStages::FRAGMENT,
2093 ty: wgpu::BindingType::Buffer {
2094 ty: wgpu::BufferBindingType::Uniform,
2095 has_dynamic_offset: false,
2096 min_binding_size: None,
2097 },
2098 count: None,
2099 },
2100 ],
2101 });
2102 let outline_edge_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
2103 label: Some("outline_edge_layout"),
2104 bind_group_layouts: &[&outline_edge_bgl],
2105 push_constant_ranges: &[],
2106 });
2107 let outline_edge_pipeline =
2108 device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
2109 label: Some("outline_edge_pipeline"),
2110 layout: Some(&outline_edge_layout),
2111 vertex: wgpu::VertexState {
2112 module: &outline_edge_shader,
2113 entry_point: Some("vs_main"),
2114 buffers: &[],
2115 compilation_options: wgpu::PipelineCompilationOptions::default(),
2116 },
2117 fragment: Some(wgpu::FragmentState {
2118 module: &outline_edge_shader,
2119 entry_point: Some("fs_main"),
2120 targets: &[Some(wgpu::ColorTargetState {
2121 format: target_format,
2122 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
2123 write_mask: wgpu::ColorWrites::ALL,
2124 })],
2125 compilation_options: wgpu::PipelineCompilationOptions::default(),
2126 }),
2127 primitive: wgpu::PrimitiveState {
2128 topology: wgpu::PrimitiveTopology::TriangleList,
2129 cull_mode: None,
2130 ..Default::default()
2131 },
2132 depth_stencil: None,
2133 multisample: wgpu::MultisampleState::default(),
2134 multiview: None,
2135 cache: pipeline_cache.as_ref(),
2136 });
2137
2138 let xray_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
2140 label: Some("xray_pipeline"),
2141 layout: Some(&outline_pipeline_layout),
2142 vertex: wgpu::VertexState {
2143 module: &xray_shader,
2144 entry_point: Some("vs_main"),
2145 buffers: &[Vertex::buffer_layout()],
2146 compilation_options: wgpu::PipelineCompilationOptions::default(),
2147 },
2148 fragment: Some(wgpu::FragmentState {
2149 module: &xray_shader,
2150 entry_point: Some("fs_main"),
2151 targets: &[Some(wgpu::ColorTargetState {
2152 format: target_format,
2153 blend: Some(wgpu::BlendState::ALPHA_BLENDING),
2154 write_mask: wgpu::ColorWrites::ALL,
2155 })],
2156 compilation_options: wgpu::PipelineCompilationOptions::default(),
2157 }),
2158 primitive: wgpu::PrimitiveState {
2159 topology: wgpu::PrimitiveTopology::TriangleList,
2160 cull_mode: None,
2161 ..Default::default()
2162 },
2163 depth_stencil: Some(wgpu::DepthStencilState {
2164 format: wgpu::TextureFormat::Depth24PlusStencil8,
2165 depth_write_enabled: false,
2166 depth_compare: wgpu::CompareFunction::Always,
2167 stencil: wgpu::StencilState::default(),
2168 bias: wgpu::DepthBiasState::default(),
2169 }),
2170 multisample: wgpu::MultisampleState {
2171 count: sample_count,
2172 mask: !0,
2173 alpha_to_coverage_enabled: false,
2174 },
2175 multiview: None,
2176 cache: pipeline_cache.as_ref(),
2177 });
2178
2179 let skybox_shader = crate::resources::builders::wgsl_module(
2181 device,
2182 "skybox_shader",
2183 crate::resources::builders::wgsl_source!("skybox"),
2184 );
2185 let skybox_pipeline_layout =
2186 device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
2187 label: Some("skybox_pipeline_layout"),
2188 bind_group_layouts: &[&camera_bgl],
2189 push_constant_ranges: &[],
2190 });
2191 let skybox_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
2192 label: Some("skybox_pipeline"),
2193 layout: Some(&skybox_pipeline_layout),
2194 vertex: wgpu::VertexState {
2195 module: &skybox_shader,
2196 entry_point: Some("vs_main"),
2197 buffers: &[],
2198 compilation_options: wgpu::PipelineCompilationOptions::default(),
2199 },
2200 fragment: Some(wgpu::FragmentState {
2201 module: &skybox_shader,
2202 entry_point: Some("fs_main"),
2203 targets: &[Some(wgpu::ColorTargetState {
2204 format: wgpu::TextureFormat::Rgba16Float,
2205 blend: None,
2206 write_mask: wgpu::ColorWrites::ALL,
2207 })],
2208 compilation_options: wgpu::PipelineCompilationOptions::default(),
2209 }),
2210 primitive: wgpu::PrimitiveState {
2211 topology: wgpu::PrimitiveTopology::TriangleList,
2212 cull_mode: None,
2213 ..Default::default()
2214 },
2215 depth_stencil: Some(wgpu::DepthStencilState {
2216 format: wgpu::TextureFormat::Depth24PlusStencil8,
2217 depth_write_enabled: false,
2219 depth_compare: wgpu::CompareFunction::Equal,
2220 stencil: wgpu::StencilState::default(),
2221 bias: wgpu::DepthBiasState::default(),
2222 }),
2223 multisample: wgpu::MultisampleState::default(),
2224 multiview: None,
2225 cache: pipeline_cache.as_ref(),
2226 });
2227
2228 mark("misc_pipelines");
2229
2230 let resources = Self {
2233 target_format,
2234 sample_count,
2235 pipeline_cache,
2236 solid_pipeline,
2237 deform,
2238 solid_two_sided_pipeline,
2239 transparent_pipeline,
2240 wireframe_pipeline,
2241 camera_uniform_buf,
2242 light_uniform_buf,
2243 light_storage_buf,
2244 clustered,
2245 camera_bind_group,
2246 camera_bind_group_layout: camera_bgl,
2247 object_bind_group_layout: object_bgl,
2248 mesh_store: {
2249 let mut store = crate::resources::mesh::mesh_store::MeshStore::new();
2250 store.insert(cube_mesh);
2251 store
2252 },
2253 lod_groups: crate::resources::mesh::lod::LodGroupStore::new(),
2254 shadow_map_texture,
2255 shadow_map_view,
2256 shadow_sampler,
2257 point_shadow_cube_texture,
2258 point_shadow_cube_view,
2259 point_shadow_face_views,
2260 shadow_point_pipeline,
2261 shadow_point_face_bind_group_layout: shadow_point_face_bgl,
2262 shadow_point_face_buf,
2263 shadow_point_face_bind_group,
2264 shadow_pipeline,
2265 shadow_pipeline_two_sided,
2266 shadow_camera_bind_group_layout: shadow_camera_bgl,
2267 shadow_uniform_buf,
2268 shadow_bind_group,
2269 shadow_info_buf,
2270 shadow_atlas_size: SHADOW_ATLAS_SIZE,
2271 shadow_atlas_depth_sampler,
2272 shadow_atlas_viewer_pipeline,
2273 shadow_atlas_viewer_bg,
2274 shadow_atlas_viewer_buf,
2275 debug_frag_sentinel_buf,
2276 gizmo_pipeline,
2277 gizmo_vertex_buffer,
2278 gizmo_index_buffer,
2279 gizmo_index_count,
2280 gizmo_uniform_buf,
2281 gizmo_bind_group,
2282 gizmo_bind_group_layout: gizmo_bgl,
2283 overlay_pipeline,
2284 overlay_line_pipeline,
2285 grid_pipeline,
2286 grid_uniform_buf,
2287 grid_bind_group,
2288 grid_bind_group_layout: grid_bgl,
2289 ground_plane_pipeline,
2290 _ground_plane_bgl: ground_plane_bgl,
2291 ground_plane_uniform_buf,
2292 ground_plane_bind_group,
2293 overlay_bind_group_layout: overlay_bgl,
2294 constraint_line_buffers: Vec::new(),
2295 axes_pipeline,
2296 axes_vertex_buffer,
2297 axes_vertex_count: 0,
2298 texture_bind_group_layout: texture_bgl,
2299 fallback_texture,
2300 fallback_normal_map,
2301 fallback_normal_map_view,
2302 fallback_ao_map,
2303 fallback_ao_map_view,
2304 fallback_metallic_roughness_texture,
2305 fallback_metallic_roughness_texture_view,
2306 fallback_emissive_texture,
2307 fallback_emissive_texture_view,
2308 material_sampler,
2309 lut_sampler,
2310 content: crate::resources::types::ContentResources {
2311 material_bind_groups: std::collections::HashMap::new(),
2312 textures: crate::resources::material::texture_store::TextureStore::new(),
2313 polyline_store: crate::resources::PolylineStore::new(),
2314 streamtube_store: crate::resources::StreamtubeStore::new(),
2315 tube_store: crate::resources::TubeStore::new(),
2316 ribbon_store: crate::resources::RibbonStore::new(),
2317 point_cloud_store: crate::resources::PointCloudStore::new(),
2318 glyph_set_store: crate::resources::GlyphSetStore::new(),
2319 tensor_glyph_set_store: crate::resources::TensorGlyphSetStore::new(),
2320 sprite_set_store: crate::resources::SpriteSetStore::new(),
2321 sprite_instance_set_store: crate::resources::SpriteInstanceSetStore::new(),
2322 gaussian_splat_store: crate::resources::types::GaussianSplatStore::new(),
2323 volume_textures: crate::resources::handle::Registry::default(),
2324 projected_tet_store: crate::resources::handle::Registry::default(),
2325 glyph_atlas: crate::resources::overlay::font::GlyphAtlas::new(device),
2326 overlay_textures: crate::resources::handle::Registry::default(),
2327 matcap_textures: Vec::new(),
2328 matcap_views: Vec::new(),
2329 matcap_sampler: None,
2330 fallback_matcap_view: None,
2331 matcaps_initialized: false,
2332 builtin_matcap_ids: None,
2333 colourmap_textures: Vec::new(),
2334 colourmap_views: Vec::new(),
2335 colourmaps_cpu: Vec::new(),
2336 fallback_lut_texture,
2337 fallback_lut_view,
2338 fallback_scalar_buf,
2339 fallback_face_colour_buf,
2340 fallback_warp_buf,
2341 fallback_position_override_buf,
2342 fallback_normal_override_buf,
2343 builtin_colourmap_ids: None,
2344 colourmaps_initialized: false,
2345 },
2346 jobs: std::sync::Mutex::new(crate::resources::upload_jobs::JobRunner::new()),
2347 job_results: crate::resources::upload_jobs::JobResults::default(),
2348 fallback_textures_uploaded: false,
2349 post: crate::resources::postprocess::PostProcessResources::default(),
2350 clip_planes_uniform_buf,
2351 clip_volume_uniform_buf,
2352 outline: crate::resources::types::OutlineResources {
2353 bind_group_layout: outline_bgl,
2354 mask_pipeline: outline_mask_pipeline,
2355 mask_two_sided_pipeline: outline_mask_two_sided_pipeline,
2356 edge_pipeline: outline_edge_pipeline,
2357 edge_bgl: outline_edge_bgl,
2358 xray_pipeline,
2359 splat_mask_pipeline: splat_outline_mask_pipeline,
2360 colour_texture: None,
2361 colour_view: None,
2362 depth_texture: None,
2363 depth_view: None,
2364 target_size: [0, 0],
2365 composite_pipeline_single: None,
2366 composite_pipeline_msaa: None,
2367 composite_pipeline_hdr: None,
2368 composite_bgl: None,
2369 composite_bind_group: None,
2370 composite_sampler: None,
2371 },
2372 instancing: crate::resources::mesh::instancing::InstancingResources::default(),
2373 cull: crate::resources::mesh::instancing::CullResources::default(),
2374 lic: crate::resources::postprocess::LicResources::default(),
2375 hdr_solid_pipeline: None,
2376 hdr_solid_two_sided_pipeline: None,
2377 hdr_transparent_pipeline: None,
2378 hdr_wireframe_pipeline: None,
2379 hdr_overlay_pipeline: None,
2380 gaussian_splat:
2381 crate::resources::scivis::gaussian_splat::GaussianSplatResources::default(),
2382 sprite: crate::resources::scivis::sprite::SpriteResources::default(),
2383 point_cloud_pipeline: None,
2384 point_cloud_bgl: None,
2385 glyph: crate::resources::scivis::glyph::GlyphResources::default(),
2386 tensor_glyph: crate::resources::scivis::glyph::TensorGlyphResources::default(),
2387 volume: crate::resources::volume::volumes::VolumeResources::default(),
2388 polyline: crate::resources::scivis::polyline::PolylineResources::default(),
2389 streamtube: crate::resources::scivis::tube::StreamtubeResources::default(),
2390 ribbon: crate::resources::scivis::tube::RibbonResources::default(),
2391 image_slice: crate::resources::types::ImageSliceResources::default(),
2392 compute_filter_pipeline: None,
2393 compute_filter_bgl: None,
2394 oit: crate::resources::postprocess::OitResources::default(),
2395 pt: crate::resources::types::ProjectedTetResources::default(),
2396 scatter: crate::resources::volume::scatter_volume::ScatterResources::default(),
2398 ibl_irradiance_view: None,
2400 ibl_prefiltered_view: None,
2401 ibl_brdf_lut_view: None,
2402 ibl_sampler,
2403 ibl_skybox_view: None,
2404 ibl_fallback_texture,
2405 ibl_fallback_view,
2406 ibl_fallback_brdf_texture,
2407 ibl_fallback_brdf_view,
2408 ibl_irradiance_texture: None,
2409 ibl_prefiltered_texture: None,
2410 ibl_brdf_lut_texture: None,
2411 ibl_skybox_texture: None,
2412 skybox_pipeline,
2413 pick: crate::resources::types::PickResources::default(),
2414 implicit: crate::resources::types::ImplicitResources::default(),
2415 mc: crate::resources::volume::gpu_marching_cubes::McResources::default(),
2416
2417 particle: crate::resources::gpu::gpu_particles::ParticleResources::default(),
2418 screen_image: crate::resources::types::ScreenImageResources::default(),
2419 sub_highlight: crate::resources::types::SubHighlightResources::default(),
2420 overlay_text: crate::resources::overlay::overlay_text::OverlayTextResources::default(),
2421 overlay_shape: crate::resources::overlay::overlay_shape::OverlayShapeResources::default(
2422 ),
2423 backdrop_blur: crate::resources::overlay::overlay_shape::BackdropBlurResources::default(
2424 ),
2425 frame_upload_bytes: 0,
2426 occlusion_culling_enabled: false,
2427 decal: crate::resources::decal::DecalResources::default(),
2428 };
2429 tracing::info!(
2434 target: "viewport_lib::init",
2435 ms = init_start.elapsed().as_secs_f32() * 1000.0,
2436 "gpu resources init total"
2437 );
2438 resources
2439 }
2440}