1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
|
use crate::{scene_prepare::ScenePreparer, scene_render::ScenePipeline};
use anyhow::{Result, anyhow};
use log::{info, warn};
use pollster::FutureExt;
use std::sync::Arc;
use weareshared::tree::SceneTree;
use wgpu::{
Backends, CommandEncoderDescriptor, Device, DeviceDescriptor, Features, Instance,
InstanceDescriptor, Limits, MaintainBase, PowerPreference, Queue, RequestAdapterOptions,
Surface, SurfaceConfiguration, TextureViewDescriptor,
};
use winit::window::Window;
pub struct Renderer<'a> {
surface: Surface<'a>,
queue: Queue,
device: Arc<Device>,
surface_configuration: SurfaceConfiguration,
scene_pipeline: ScenePipeline,
pub scene_prepare: ScenePreparer,
surface_needs_reconfigure: bool,
}
impl<'a> Renderer<'a> {
pub fn new(window: &'a Window) -> Result<Self> {
info!("wgpu init");
let instance = Instance::new(InstanceDescriptor {
backends: Backends::all(),
..Default::default()
});
let surface = instance.create_surface(window)?;
let adapter = instance
.request_adapter(&RequestAdapterOptions {
compatible_surface: Some(&surface),
power_preference: PowerPreference::HighPerformance,
..Default::default()
})
.block_on()
.ok_or(anyhow!("no adapter found"))?;
let (device, queue) = adapter
.request_device(
&DeviceDescriptor {
required_features: Features::PUSH_CONSTANTS,
required_limits: Limits {
max_push_constant_size: 64,
max_vertex_buffers: 16,
..Limits::default()
},
..Default::default()
},
None,
)
.block_on()?;
let surface_configuration = surface
.get_default_config(&adapter, 256, 256)
.ok_or(anyhow!("no default config"))?;
surface.configure(&device, &surface_configuration);
let device = Arc::new(device);
Ok(Self {
scene_pipeline: ScenePipeline::new(&device, surface_configuration.format),
scene_prepare: ScenePreparer::new(device.clone()),
surface,
device,
queue,
surface_configuration,
surface_needs_reconfigure: false,
})
}
pub fn resize(&mut self, width: u32, height: u32) {
self.surface_configuration.width = width;
self.surface_configuration.height = height;
self.surface
.configure(&self.device, &self.surface_configuration);
}
pub fn draw(&mut self, scene: &SceneTree) -> Result<()> {
if self.surface_needs_reconfigure {
self.surface
.configure(&self.device, &self.surface_configuration);
self.surface_needs_reconfigure = false
}
let target = self.surface.get_current_texture()?;
if target.suboptimal {
warn!("suboptimal swapchain texture");
self.surface_needs_reconfigure = true;
}
let target_view = target
.texture
.create_view(&TextureViewDescriptor::default());
let mut commands = self
.device
.create_command_encoder(&CommandEncoderDescriptor { label: None });
self.scene_pipeline.draw(
&mut commands,
&target_view,
scene,
&self.scene_prepare.prefabs,
&mut self.scene_prepare.prefabs_needed,
);
let i = self.queue.submit(Some(commands.finish()));
self.device.poll(MaintainBase::WaitForSubmissionIndex(i));
target.present();
Ok(())
}
}
|