rrtrace 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/src/renderer.rs ADDED
@@ -0,0 +1,751 @@
1
+ use crate::renderer::vertex_arena::{AllocationId, VertexArena};
2
+ use crate::trace_state::{CallBox, SlowTrace, VISIBLE_DURATION, encode_time};
3
+ use glam::{Mat4, Vec3};
4
+ use std::cmp::{Ordering, Reverse};
5
+ use std::collections::btree_map::Entry;
6
+ use std::collections::{BTreeMap, BinaryHeap};
7
+ use std::fmt::{Debug, Formatter};
8
+ use std::sync::Arc;
9
+ use std::{fmt, iter};
10
+ use wgpu::BufferUsages;
11
+ use wgpu::util::DeviceExt;
12
+
13
+ mod vertex_arena;
14
+
15
+ #[repr(C)]
16
+ #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
17
+ struct Vertex {
18
+ position: [f32; 3],
19
+ }
20
+
21
+ impl Vertex {
22
+ const fn new(x: f32, y: f32, z: f32) -> Self {
23
+ Self {
24
+ position: [x, y, z],
25
+ }
26
+ }
27
+
28
+ fn desc() -> wgpu::VertexBufferLayout<'static> {
29
+ wgpu::VertexBufferLayout {
30
+ array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
31
+ step_mode: wgpu::VertexStepMode::Vertex,
32
+ attributes: &[wgpu::VertexAttribute {
33
+ offset: 0,
34
+ shader_location: 0,
35
+ format: wgpu::VertexFormat::Float32x3,
36
+ }],
37
+ }
38
+ }
39
+ }
40
+
41
+ impl CallBox {
42
+ fn desc() -> wgpu::VertexBufferLayout<'static> {
43
+ wgpu::VertexBufferLayout {
44
+ array_stride: std::mem::size_of::<CallBox>() as wgpu::BufferAddress,
45
+ step_mode: wgpu::VertexStepMode::Instance,
46
+ attributes: &[
47
+ wgpu::VertexAttribute {
48
+ offset: 0,
49
+ shader_location: 1,
50
+ format: wgpu::VertexFormat::Uint32x2,
51
+ },
52
+ wgpu::VertexAttribute {
53
+ offset: 8,
54
+ shader_location: 2,
55
+ format: wgpu::VertexFormat::Uint32x2,
56
+ },
57
+ wgpu::VertexAttribute {
58
+ offset: 16,
59
+ shader_location: 3,
60
+ format: wgpu::VertexFormat::Uint32,
61
+ },
62
+ wgpu::VertexAttribute {
63
+ offset: 20,
64
+ shader_location: 4,
65
+ format: wgpu::VertexFormat::Uint32,
66
+ },
67
+ ],
68
+ }
69
+ }
70
+ }
71
+
72
+ #[repr(C)]
73
+ #[derive(Copy, Clone, Debug, Default, bytemuck::Pod, bytemuck::Zeroable)]
74
+ struct GCBox {
75
+ time: [u32; 2],
76
+ }
77
+
78
+ impl GCBox {
79
+ fn desc() -> wgpu::VertexBufferLayout<'static> {
80
+ wgpu::VertexBufferLayout {
81
+ array_stride: std::mem::size_of::<GCBox>() as wgpu::BufferAddress,
82
+ step_mode: wgpu::VertexStepMode::Instance,
83
+ attributes: &[
84
+ wgpu::VertexAttribute {
85
+ offset: 0,
86
+ shader_location: 1,
87
+ format: wgpu::VertexFormat::Uint32x2,
88
+ },
89
+ ],
90
+ }
91
+ }
92
+ }
93
+
94
+ const VERTICES: &[Vertex] = &[
95
+ Vertex::new(0.0, 0.0, 0.2),
96
+ Vertex::new(1.0, 0.0, 0.2),
97
+ Vertex::new(0.0, 1.0, 0.2),
98
+ Vertex::new(1.0, 1.0, 0.2),
99
+ Vertex::new(0.0, 0.0, 0.8),
100
+ Vertex::new(1.0, 0.0, 0.8),
101
+ Vertex::new(0.0, 1.0, 0.8),
102
+ Vertex::new(1.0, 1.0, 0.8),
103
+ ];
104
+
105
+ const INDICES: &[u16] = &[
106
+ 0, 2, 3, 0, 3, 1, 1, 3, 7, 1, 7, 5, 5, 7, 6, 5, 6, 4, 4, 6, 2, 4, 2, 0, 2, 6, 7, 2, 7, 3,
107
+ ];
108
+
109
+ #[repr(C)]
110
+ #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
111
+ struct GCVertex {
112
+ position: [f32; 2],
113
+ }
114
+
115
+ impl GCVertex {
116
+ fn desc() -> wgpu::VertexBufferLayout<'static> {
117
+ wgpu::VertexBufferLayout {
118
+ array_stride: std::mem::size_of::<GCVertex>() as wgpu::BufferAddress,
119
+ step_mode: wgpu::VertexStepMode::Vertex,
120
+ attributes: &[wgpu::VertexAttribute {
121
+ offset: 0,
122
+ shader_location: 0,
123
+ format: wgpu::VertexFormat::Float32x2,
124
+ }],
125
+ }
126
+ }
127
+ }
128
+
129
+ const GC_VERTICES: &[GCVertex] = &[
130
+ GCVertex {
131
+ position: [0.0, 0.0],
132
+ },
133
+ GCVertex {
134
+ position: [0.0, 1.0],
135
+ },
136
+ GCVertex {
137
+ position: [1.0, 0.0],
138
+ },
139
+ GCVertex {
140
+ position: [1.0, 1.0],
141
+ },
142
+ ];
143
+
144
+ #[repr(C)]
145
+ #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
146
+ struct CameraUniform {
147
+ view_proj: [[f32; 4]; 4],
148
+ base_time: [u32; 2],
149
+ max_depth: u32,
150
+ num_threads: u32,
151
+ }
152
+
153
+ #[repr(C)]
154
+ #[derive(Copy, Clone, Debug, bytemuck::Pod, bytemuck::Zeroable)]
155
+ struct ThreadInfo {
156
+ lane_id: u32,
157
+ }
158
+
159
+ struct SurfaceState {
160
+ surface: wgpu::Surface<'static>,
161
+ config: wgpu::SurfaceConfiguration,
162
+ render_pipeline: wgpu::RenderPipeline,
163
+ gc_pipeline: wgpu::RenderPipeline,
164
+ depth_texture: wgpu::TextureView,
165
+ }
166
+
167
+ #[derive(Debug)]
168
+ struct ThreadArena {
169
+ used_segments: usize,
170
+ vertex: VertexArena<CallBox>,
171
+ }
172
+
173
+ #[derive(Debug, Eq, PartialEq)]
174
+ struct TraceBatch {
175
+ end_time: u64,
176
+ thread_data: Vec<(u32, AllocationId)>,
177
+ gc_data: Option<AllocationId>,
178
+ max_depth: u32,
179
+ }
180
+
181
+ impl PartialOrd for TraceBatch {
182
+ fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
183
+ Some(self.cmp(other))
184
+ }
185
+ }
186
+
187
+ impl Ord for TraceBatch {
188
+ fn cmp(&self, other: &Self) -> Ordering {
189
+ self.end_time.cmp(&other.end_time)
190
+ }
191
+ }
192
+
193
+ pub struct Renderer {
194
+ instance: wgpu::Instance,
195
+ device: wgpu::Device,
196
+ queue: wgpu::Queue,
197
+ adapter: wgpu::Adapter,
198
+ surface_state: Option<SurfaceState>,
199
+ shader: wgpu::ShaderModule,
200
+ render_pipeline_layout: wgpu::PipelineLayout,
201
+ vertex_buffer: wgpu::Buffer,
202
+ gc_vertex_buffer: wgpu::Buffer,
203
+ index_buffer: wgpu::Buffer,
204
+ num_indices: u32,
205
+ camera_uniform: CameraUniform,
206
+ camera_buffer: wgpu::Buffer,
207
+ camera_bind_group: wgpu::BindGroup,
208
+ lane_alignment: u32,
209
+ trace_queue: Arc<crossbeam_queue::SegQueue<SlowTrace>>,
210
+ data_per_thread: BTreeMap<u32, ThreadArena>,
211
+ gc_vertex: VertexArena<GCBox>,
212
+ thread_queue: BinaryHeap<Reverse<TraceBatch>>,
213
+ base_time: u64,
214
+ depth: MultiSet<u32>,
215
+ }
216
+
217
+ impl Renderer {
218
+ pub fn new(
219
+ instance: wgpu::Instance,
220
+ adapter: wgpu::Adapter,
221
+ device: wgpu::Device,
222
+ queue: wgpu::Queue,
223
+ trace_queue: Arc<crossbeam_queue::SegQueue<SlowTrace>>,
224
+ ) -> Self {
225
+ let limits = device.limits();
226
+ let lane_alignment = limits.min_uniform_buffer_offset_alignment;
227
+ let shader = device.create_shader_module(wgpu::include_wgsl!("shader.wgsl"));
228
+
229
+ let camera_uniform = CameraUniform {
230
+ view_proj: Mat4::IDENTITY.to_cols_array_2d(),
231
+ base_time: [0, 0],
232
+ max_depth: 0,
233
+ num_threads: 0,
234
+ };
235
+ let camera_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
236
+ label: Some("Camera Buffer"),
237
+ contents: bytemuck::cast_slice(&[camera_uniform]),
238
+ usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
239
+ });
240
+
241
+ const MAX_LANES: u32 = 256;
242
+ let thread_info_buffer_size = MAX_LANES * lane_alignment;
243
+ let mut thread_info_data = vec![0u8; thread_info_buffer_size as usize];
244
+ for i in 0..MAX_LANES {
245
+ let offset = (i * lane_alignment) as usize;
246
+ let info = ThreadInfo { lane_id: i };
247
+ thread_info_data[offset..offset + 4].copy_from_slice(bytemuck::bytes_of(&info));
248
+ }
249
+
250
+ let thread_info_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
251
+ label: Some("Thread Info Buffer"),
252
+ contents: &thread_info_data,
253
+ usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
254
+ });
255
+
256
+ let camera_bind_group_layout =
257
+ device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
258
+ entries: &[
259
+ wgpu::BindGroupLayoutEntry {
260
+ binding: 0,
261
+ visibility: wgpu::ShaderStages::VERTEX,
262
+ ty: wgpu::BindingType::Buffer {
263
+ ty: wgpu::BufferBindingType::Uniform,
264
+ has_dynamic_offset: false,
265
+ min_binding_size: None,
266
+ },
267
+ count: None,
268
+ },
269
+ wgpu::BindGroupLayoutEntry {
270
+ binding: 1,
271
+ visibility: wgpu::ShaderStages::VERTEX,
272
+ ty: wgpu::BindingType::Buffer {
273
+ ty: wgpu::BufferBindingType::Uniform,
274
+ has_dynamic_offset: true,
275
+ min_binding_size: None,
276
+ },
277
+ count: None,
278
+ },
279
+ ],
280
+ label: Some("camera_bind_group_layout"),
281
+ });
282
+
283
+ let camera_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
284
+ layout: &camera_bind_group_layout,
285
+ entries: &[
286
+ wgpu::BindGroupEntry {
287
+ binding: 0,
288
+ resource: camera_buffer.as_entire_binding(),
289
+ },
290
+ wgpu::BindGroupEntry {
291
+ binding: 1,
292
+ resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
293
+ buffer: &thread_info_buffer,
294
+ offset: 0,
295
+ size: wgpu::BufferSize::new(std::mem::size_of::<ThreadInfo>() as u64),
296
+ }),
297
+ },
298
+ ],
299
+ label: Some("camera_bind_group"),
300
+ });
301
+
302
+ let render_pipeline_layout =
303
+ device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
304
+ label: Some("Render Pipeline Layout"),
305
+ bind_group_layouts: &[&camera_bind_group_layout],
306
+ immediate_size: 0,
307
+ });
308
+
309
+ let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
310
+ label: Some("Vertex Buffer"),
311
+ contents: bytemuck::cast_slice(VERTICES),
312
+ usage: wgpu::BufferUsages::VERTEX,
313
+ });
314
+ let gc_vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
315
+ label: Some("GC Vertex Buffer"),
316
+ contents: bytemuck::cast_slice(GC_VERTICES),
317
+ usage: wgpu::BufferUsages::VERTEX,
318
+ });
319
+ let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
320
+ label: Some("Index Buffer"),
321
+ contents: bytemuck::cast_slice(INDICES),
322
+ usage: wgpu::BufferUsages::INDEX,
323
+ });
324
+ let num_indices = INDICES.len() as u32;
325
+
326
+ Self {
327
+ instance,
328
+ device: device.clone(),
329
+ queue: queue.clone(),
330
+ adapter,
331
+ surface_state: None,
332
+ shader,
333
+ render_pipeline_layout,
334
+ vertex_buffer,
335
+ gc_vertex_buffer,
336
+ index_buffer,
337
+ num_indices,
338
+ camera_uniform,
339
+ camera_buffer,
340
+ camera_bind_group,
341
+ lane_alignment,
342
+ trace_queue,
343
+ data_per_thread: BTreeMap::new(),
344
+ gc_vertex: VertexArena::new(
345
+ device,
346
+ queue,
347
+ BufferUsages::COPY_DST | BufferUsages::VERTEX,
348
+ ),
349
+ thread_queue: BinaryHeap::new(),
350
+ base_time: 0,
351
+ depth: MultiSet::new(),
352
+ }
353
+ }
354
+
355
+ pub fn set_window(&mut self, window: std::sync::Arc<winit::window::Window>) {
356
+ let size = window.inner_size();
357
+ let surface = self.instance.create_surface(window).unwrap();
358
+
359
+ let surface_caps = surface.get_capabilities(&self.adapter);
360
+ let surface_format = surface_caps
361
+ .formats
362
+ .iter()
363
+ .copied()
364
+ .find(|f| f.is_srgb())
365
+ .unwrap_or(surface_caps.formats[0]);
366
+ let config = wgpu::SurfaceConfiguration {
367
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
368
+ format: surface_format,
369
+ width: size.width,
370
+ height: size.height,
371
+ present_mode: surface_caps.present_modes[0],
372
+ alpha_mode: surface_caps.alpha_modes[0],
373
+ view_formats: vec![],
374
+ desired_maximum_frame_latency: 2,
375
+ };
376
+ surface.configure(&self.device, &config);
377
+
378
+ let render_pipeline = self
379
+ .device
380
+ .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
381
+ label: Some("Render Pipeline"),
382
+ layout: Some(&self.render_pipeline_layout),
383
+ vertex: wgpu::VertexState {
384
+ module: &self.shader,
385
+ entry_point: Some("vs_main"),
386
+ buffers: &[Vertex::desc(), CallBox::desc()],
387
+ compilation_options: Default::default(),
388
+ },
389
+ fragment: Some(wgpu::FragmentState {
390
+ module: &self.shader,
391
+ entry_point: Some("fs_main"),
392
+ targets: &[Some(wgpu::ColorTargetState {
393
+ format: config.format,
394
+ blend: Some(wgpu::BlendState::REPLACE),
395
+ write_mask: wgpu::ColorWrites::ALL,
396
+ })],
397
+ compilation_options: Default::default(),
398
+ }),
399
+ primitive: wgpu::PrimitiveState {
400
+ topology: wgpu::PrimitiveTopology::TriangleList,
401
+ strip_index_format: None,
402
+ front_face: wgpu::FrontFace::Ccw,
403
+ cull_mode: Some(wgpu::Face::Front),
404
+ polygon_mode: wgpu::PolygonMode::Fill,
405
+ unclipped_depth: false,
406
+ conservative: false,
407
+ },
408
+ depth_stencil: Some(wgpu::DepthStencilState {
409
+ format: wgpu::TextureFormat::Depth32Float,
410
+ depth_write_enabled: true,
411
+ depth_compare: wgpu::CompareFunction::Less,
412
+ stencil: wgpu::StencilState::default(),
413
+ bias: wgpu::DepthBiasState::default(),
414
+ }),
415
+ multisample: wgpu::MultisampleState::default(),
416
+ cache: None,
417
+ multiview_mask: None,
418
+ });
419
+
420
+ let gc_pipeline = self
421
+ .device
422
+ .create_render_pipeline(&wgpu::RenderPipelineDescriptor {
423
+ label: Some("GC Pipeline"),
424
+ layout: Some(&self.render_pipeline_layout),
425
+ vertex: wgpu::VertexState {
426
+ module: &self.shader,
427
+ entry_point: Some("vs_gc"),
428
+ buffers: &[GCVertex::desc(), GCBox::desc()],
429
+ compilation_options: Default::default(),
430
+ },
431
+ fragment: Some(wgpu::FragmentState {
432
+ module: &self.shader,
433
+ entry_point: Some("fs_main"),
434
+ targets: &[Some(wgpu::ColorTargetState {
435
+ format: config.format,
436
+ blend: Some(wgpu::BlendState::ALPHA_BLENDING),
437
+ write_mask: wgpu::ColorWrites::ALL,
438
+ })],
439
+ compilation_options: Default::default(),
440
+ }),
441
+ primitive: wgpu::PrimitiveState {
442
+ topology: wgpu::PrimitiveTopology::TriangleStrip,
443
+ strip_index_format: None,
444
+ front_face: wgpu::FrontFace::Ccw,
445
+ cull_mode: None,
446
+ polygon_mode: wgpu::PolygonMode::Fill,
447
+ unclipped_depth: false,
448
+ conservative: false,
449
+ },
450
+ depth_stencil: Some(wgpu::DepthStencilState {
451
+ format: wgpu::TextureFormat::Depth32Float,
452
+ depth_write_enabled: false,
453
+ depth_compare: wgpu::CompareFunction::Less,
454
+ stencil: wgpu::StencilState::default(),
455
+ bias: wgpu::DepthBiasState::default(),
456
+ }),
457
+ multisample: wgpu::MultisampleState::default(),
458
+ cache: None,
459
+ multiview_mask: None,
460
+ });
461
+
462
+ let depth_texture = Self::create_depth_texture(&self.device, &config);
463
+
464
+ self.surface_state = Some(SurfaceState {
465
+ surface,
466
+ config,
467
+ render_pipeline,
468
+ gc_pipeline,
469
+ depth_texture,
470
+ });
471
+ }
472
+
473
+ fn create_depth_texture(
474
+ device: &wgpu::Device,
475
+ config: &wgpu::SurfaceConfiguration,
476
+ ) -> wgpu::TextureView {
477
+ let size = wgpu::Extent3d {
478
+ width: config.width,
479
+ height: config.height,
480
+ depth_or_array_layers: 1,
481
+ };
482
+ let desc = wgpu::TextureDescriptor {
483
+ label: Some("Depth Texture"),
484
+ size,
485
+ mip_level_count: 1,
486
+ sample_count: 1,
487
+ dimension: wgpu::TextureDimension::D2,
488
+ format: wgpu::TextureFormat::Depth32Float,
489
+ usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::TEXTURE_BINDING,
490
+ view_formats: &[],
491
+ };
492
+ let texture = device.create_texture(&desc);
493
+ texture.create_view(&wgpu::TextureViewDescriptor::default())
494
+ }
495
+
496
+ pub fn resize(&mut self, new_size: winit::dpi::PhysicalSize<u32>) {
497
+ if let Some(state) = &mut self.surface_state {
498
+ if new_size.width > 0 && new_size.height > 0 {
499
+ state.config.width = new_size.width;
500
+ state.config.height = new_size.height;
501
+ state.surface.configure(&self.device, &state.config);
502
+ state.depth_texture = Self::create_depth_texture(&self.device, &state.config);
503
+ }
504
+ }
505
+ }
506
+
507
+ pub fn sync(&mut self) -> bool {
508
+ let mut updated = false;
509
+ while let Some(trace) = self.trace_queue.pop() {
510
+ updated = true;
511
+ let mut allocation_ids = Vec::new();
512
+ for (thread_id, call_box) in trace.data() {
513
+ let s = self.data_per_thread.entry(thread_id).or_insert_with(|| ThreadArena {
514
+ used_segments: 0,
515
+ vertex: VertexArena::new(
516
+ self.device.clone(),
517
+ self.queue.clone(),
518
+ BufferUsages::COPY_DST | BufferUsages::VERTEX,
519
+ ),
520
+ });
521
+ s.used_segments += 1;
522
+ let (allocation_id, slot) = s.vertex.alloc(call_box.len());
523
+ slot.copy_from_slice(call_box);
524
+ allocation_ids.push((thread_id, allocation_id));
525
+ }
526
+
527
+ let gc_events = trace.gc_events();
528
+ let gc_data = if !gc_events.is_empty() {
529
+ let mut gc_boxes = Vec::with_capacity(gc_events.len());
530
+ for &event_time in gc_events {
531
+ gc_boxes.push(GCBox {
532
+ time: encode_time(event_time),
533
+ });
534
+ }
535
+ if !gc_boxes.is_empty() {
536
+ let (allocation_id, slot) = self.gc_vertex.alloc(gc_boxes.len());
537
+ slot.copy_from_slice(&gc_boxes);
538
+ Some(allocation_id)
539
+ } else {
540
+ None
541
+ }
542
+ } else {
543
+ None
544
+ };
545
+
546
+ let end_time = trace.end_time();
547
+ let max_depth = trace.max_depth();
548
+ self.thread_queue.push(Reverse(TraceBatch {
549
+ end_time,
550
+ max_depth,
551
+ thread_data: allocation_ids,
552
+ gc_data,
553
+ }));
554
+ self.base_time = self.base_time.max(end_time);
555
+ self.depth.insert(max_depth);
556
+ }
557
+ while let Some(Reverse(TraceBatch { end_time, .. })) = self.thread_queue.peek()
558
+ && end_time + VISIBLE_DURATION < self.base_time
559
+ {
560
+ let Reverse(TraceBatch {
561
+ thread_data,
562
+ max_depth,
563
+ gc_data,
564
+ ..
565
+ }) = self.thread_queue.pop().unwrap();
566
+ self.depth.remove(max_depth);
567
+ for (thread_id, allocation_id) in thread_data {
568
+ match self.data_per_thread.entry(thread_id) {
569
+ Entry::Vacant(_) => unreachable!(),
570
+ Entry::Occupied(mut s) => {
571
+ let s_ref = s.get_mut();
572
+ s_ref.used_segments -= 1;
573
+ if s_ref.used_segments == 0 {
574
+ s.remove();
575
+ } else {
576
+ s_ref.vertex.dealloc(allocation_id);
577
+ }
578
+ }
579
+ }
580
+ }
581
+ if let Some(gc_allocation_id) = gc_data {
582
+ self.gc_vertex.dealloc(gc_allocation_id);
583
+ }
584
+ }
585
+ updated
586
+ }
587
+
588
+ pub fn render(&mut self) -> Result<(), wgpu::SurfaceError> {
589
+ let Some(state) = &self.surface_state else {
590
+ return Ok(());
591
+ };
592
+
593
+ let aspect = if let Some(state) = &self.surface_state {
594
+ state.config.width as f32 / state.config.height as f32
595
+ } else {
596
+ 1.0
597
+ };
598
+
599
+ // カメラの更新
600
+ let view = Mat4::look_at_rh(
601
+ Vec3::new(-1.0, 1.0, 2.0), // eye
602
+ Vec3::new(0.5, 0.5, 0.5), // center
603
+ Vec3::Y, // up
604
+ );
605
+ let proj = Mat4::perspective_rh(std::f32::consts::FRAC_PI_4, aspect, 0.1, 10000.0);
606
+ self.camera_uniform.view_proj = (proj * view).to_cols_array_2d();
607
+ self.camera_uniform.base_time = encode_time(self.base_time);
608
+ self.camera_uniform.max_depth = self.depth.max().map_or(1, |&m| m + 1);
609
+ self.camera_uniform.num_threads = self.data_per_thread.len() as u32;
610
+
611
+ self.queue.write_buffer(
612
+ &self.camera_buffer,
613
+ 0,
614
+ bytemuck::cast_slice(&[self.camera_uniform]),
615
+ );
616
+
617
+ let output = state.surface.get_current_texture()?;
618
+ let view = output
619
+ .texture
620
+ .create_view(&wgpu::TextureViewDescriptor::default());
621
+ let mut encoder = self
622
+ .device
623
+ .create_command_encoder(&wgpu::CommandEncoderDescriptor {
624
+ label: Some("Render Encoder"),
625
+ });
626
+
627
+ {
628
+ let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
629
+ label: Some("Render Pass"),
630
+ color_attachments: &[Some(wgpu::RenderPassColorAttachment {
631
+ view: &view,
632
+ depth_slice: None,
633
+ resolve_target: None,
634
+ ops: wgpu::Operations {
635
+ load: wgpu::LoadOp::Clear(wgpu::Color {
636
+ r: 0.01,
637
+ g: 0.02,
638
+ b: 0.05,
639
+ a: 1.0,
640
+ }),
641
+ store: wgpu::StoreOp::Store,
642
+ },
643
+ })],
644
+ depth_stencil_attachment: Some(wgpu::RenderPassDepthStencilAttachment {
645
+ view: &state.depth_texture,
646
+ depth_ops: Some(wgpu::Operations {
647
+ load: wgpu::LoadOp::Clear(1.0),
648
+ store: wgpu::StoreOp::Store,
649
+ }),
650
+ stencil_ops: None,
651
+ }),
652
+ occlusion_query_set: None,
653
+ timestamp_writes: None,
654
+ multiview_mask: None,
655
+ });
656
+
657
+ render_pass.set_pipeline(&state.render_pipeline);
658
+ render_pass.set_vertex_buffer(0, self.vertex_buffer.slice(..));
659
+ render_pass.set_index_buffer(self.index_buffer.slice(..), wgpu::IndexFormat::Uint16);
660
+
661
+ let num_indices = self.num_indices;
662
+ let camera_bind_group = &self.camera_bind_group;
663
+ let lane_alignment = self.lane_alignment;
664
+
665
+ for (lane, (_, vertices)) in self.data_per_thread.iter_mut().enumerate() {
666
+ vertices.vertex.sync();
667
+ vertices.vertex.read_buffers(|buffer, len| {
668
+ if len == 0 {
669
+ return;
670
+ }
671
+ let offset = lane as u32 * lane_alignment;
672
+ render_pass.set_bind_group(0, camera_bind_group, &[offset]);
673
+ render_pass.set_vertex_buffer(1, buffer.slice(..));
674
+ render_pass.draw_indexed(0..num_indices, 0, 0..len as u32);
675
+ });
676
+ }
677
+
678
+ render_pass.set_pipeline(&state.gc_pipeline);
679
+ render_pass.set_bind_group(0, camera_bind_group, &[0]);
680
+ self.gc_vertex.sync();
681
+ self.gc_vertex.read_buffers(|buffer, len| {
682
+ if len == 0 {
683
+ return;
684
+ }
685
+ render_pass.set_vertex_buffer(0, self.gc_vertex_buffer.slice(..));
686
+ render_pass.set_vertex_buffer(1, buffer.slice(..));
687
+ render_pass.draw(0..4, 0..len as u32);
688
+ });
689
+ }
690
+
691
+ self.queue.submit(iter::once(encoder.finish()));
692
+ output.present();
693
+
694
+ Ok(())
695
+ }
696
+ }
697
+
698
+ struct MultiSet<T> {
699
+ inner: BTreeMap<T, usize>,
700
+ }
701
+
702
+ impl<T> Default for MultiSet<T> {
703
+ fn default() -> Self {
704
+ MultiSet::new()
705
+ }
706
+ }
707
+
708
+ impl<T> Debug for MultiSet<T>
709
+ where
710
+ T: Debug,
711
+ {
712
+ fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
713
+ f.debug_set()
714
+ .entries(self.inner.iter().flat_map(|(k, &v)| iter::repeat_n(k, v)))
715
+ .finish()
716
+ }
717
+ }
718
+
719
+ impl<T> MultiSet<T> {
720
+ fn new() -> MultiSet<T> {
721
+ MultiSet {
722
+ inner: BTreeMap::new(),
723
+ }
724
+ }
725
+ }
726
+ impl<T> MultiSet<T>
727
+ where
728
+ T: Ord,
729
+ {
730
+ fn insert(&mut self, value: T) {
731
+ *self.inner.entry(value).or_default() += 1;
732
+ }
733
+
734
+ fn remove(&mut self, value: T) {
735
+ match self.inner.entry(value) {
736
+ Entry::Vacant(_) => return,
737
+ Entry::Occupied(mut entry) => {
738
+ let count = entry.get_mut();
739
+ if *count <= 1 {
740
+ entry.remove();
741
+ } else {
742
+ *count -= 1;
743
+ }
744
+ }
745
+ }
746
+ }
747
+
748
+ fn max(&self) -> Option<&T> {
749
+ self.inner.last_key_value().map(|(v, _)| v)
750
+ }
751
+ }