1use std::{
15 error::Error,
16 f32::consts::PI,
17 ffi::OsStr,
18 net::ToSocketAddrs,
19 path::{Path, PathBuf},
20 sync::{Arc, RwLock},
21};
22
23use crate::{
24 common::transform::{to_gl_pos, to_gl_rot},
25 field_compute_pipeline::{Config, FieldComputePipeline},
26 imgui_renderer::ImGuiRenderer,
27 renderer::Renderer,
28 slice_viewer::SliceViewer,
29 sound_sources::{Drive, SoundSources},
30 trans_viewer::TransViewer,
31 update_flag::UpdateFlag,
32 viewer_settings::ViewerSettings,
33 Quaternion, Vector3, SCALE,
34};
35use autd3_core::{autd3_device::AUTD3, geometry::Device, TxDatagram, FPGA_CLK_FREQ};
36use autd3_firmware_emulator::CPUEmulator;
37use crossbeam_channel::{bounded, Receiver, Sender, TryRecvError};
38use vulkano::{
39 command_buffer::{
40 AutoCommandBufferBuilder, CommandBufferUsage, RenderPassBeginInfo, SubpassContents,
41 },
42 sync::GpuFuture,
43};
44use winit::{
45 event::{Event, WindowEvent},
46 event_loop::{ControlFlow, EventLoopBuilder},
47 platform::run_return::EventLoopExtRunReturn,
48};
49
50use futures_util::future::FutureExt;
51use tokio::{runtime::Builder, sync::oneshot};
52use tonic::{transport::Server, Request, Response, Status};
53
54use autd3_protobuf::*;
55
56enum Signal {
57 ConfigGeometry(Geometry),
58 Send(TxRawData),
59 Close,
60}
61
62struct SimulatorServer {
63 rx_buf: Arc<RwLock<autd3_core::RxDatagram>>,
64 sender: Sender<Signal>,
65}
66
67#[tonic::async_trait]
68impl simulator_server::Simulator for SimulatorServer {
69 async fn config_geomety(
70 &self,
71 req: Request<Geometry>,
72 ) -> Result<Response<GeometryResponse>, Status> {
73 if self
74 .sender
75 .send(Signal::ConfigGeometry(req.into_inner()))
76 .is_err()
77 {
78 return Err(Status::unavailable("Simulator is closed"));
79 }
80 Ok(Response::new(GeometryResponse {}))
81 }
82
83 async fn send_data(&self, req: Request<TxRawData>) -> Result<Response<SendResponse>, Status> {
84 if self.sender.send(Signal::Send(req.into_inner())).is_err() {
85 return Err(Status::unavailable("Simulator is closed"));
86 }
87 Ok(Response::new(SendResponse { success: true }))
88 }
89
90 async fn read_data(&self, _: Request<ReadRequest>) -> Result<Response<RxMessage>, Status> {
91 let rx = self.rx_buf.read().unwrap();
92 Ok(Response::new(RxMessage {
93 data: rx.iter().flat_map(|c| [c.ack, c.msg_id]).collect(),
94 }))
95 }
96
97 async fn close(&self, _: Request<CloseRequest>) -> Result<Response<CloseResponse>, Status> {
98 if self.sender.send(Signal::Close).is_err() {
99 return Err(Status::unavailable("Simulator is closed"));
100 }
101 Ok(Response::new(CloseResponse { success: true }))
102 }
103}
104
105#[derive(Default)]
107pub struct Simulator {
108 window_width: Option<u32>,
109 window_height: Option<u32>,
110 vsync: Option<bool>,
111 port: Option<u16>,
112 gpu_idx: Option<i32>,
113 settings: ViewerSettings,
114 config_path: Option<PathBuf>,
115}
116
117impl Simulator {
118 pub fn new() -> Self {
119 Self {
120 window_width: None,
121 window_height: None,
122 vsync: None,
123 port: None,
124 gpu_idx: None,
125 settings: ViewerSettings::default(),
126 config_path: None,
127 }
128 }
129
130 pub fn with_window_size(mut self, width: u32, height: u32) -> Self {
132 self.window_width = Some(width);
133 self.window_height = Some(height);
134 self
135 }
136
137 pub fn with_vsync(mut self, vsync: bool) -> Self {
139 self.vsync = Some(vsync);
140 self
141 }
142
143 pub fn with_port(mut self, port: u16) -> Self {
145 self.port = Some(port);
146 self
147 }
148
149 pub fn with_gpu_idx(mut self, gpu_idx: i32) -> Self {
156 self.gpu_idx = Some(gpu_idx);
157 self
158 }
159
160 pub fn with_settings(mut self, settings: ViewerSettings) -> Self {
162 self.settings = settings;
163 self
164 }
165
166 pub fn with_config_path<S: AsRef<OsStr> + Sized>(mut self, config_path: S) -> Self {
168 self.config_path = Some(Path::new(&config_path).to_owned());
169 self
170 }
171
172 pub fn get_settings(&self) -> &ViewerSettings {
174 &self.settings
175 }
176
177 pub fn run(&mut self) -> i32 {
185 spdlog::info!("Initializing window...");
186
187 let (tx, rx) = bounded(32);
188
189 let (tx_shutdown, rx_shutdown) = oneshot::channel::<()>();
190 let port = self.port.unwrap_or(self.settings.port);
191
192 let rx_buf = Arc::new(RwLock::new(autd3_core::RxDatagram::new(0)));
193 let rx_buf_clone = rx_buf.clone();
194
195 let server_th = std::thread::spawn(move || {
196 spdlog::info!("Waiting for client connection on http://0.0.0.0:{}", port);
197 let body = async {
198 Server::builder()
199 .add_service(simulator_server::SimulatorServer::new(SimulatorServer {
200 rx_buf: rx_buf_clone,
201 sender: tx,
202 }))
203 .serve_with_shutdown(
204 format!("0.0.0.0:{port}")
205 .to_socket_addrs()
206 .unwrap()
207 .next()
208 .unwrap(),
209 rx_shutdown.map(drop),
210 )
211 .await
212 };
213 Builder::new_multi_thread()
214 .enable_all()
215 .build()
216 .unwrap()
217 .block_on(body)
218 });
219
220 self.run_simulator(server_th, rx_buf, rx, tx_shutdown)
221 }
222
223 fn run_simulator(
224 &mut self,
225 server_th: std::thread::JoinHandle<Result<(), tonic::transport::Error>>,
226 rx_buf: Arc<RwLock<autd3_core::RxDatagram>>,
227 receiver: Receiver<Signal>,
228 shutdown: tokio::sync::oneshot::Sender<()>,
229 ) -> i32 {
230 let mut event_loop = EventLoopBuilder::<()>::with_user_event().build();
231
232 let mut render = Renderer::new(
233 &event_loop,
234 "AUTD Simulator",
235 self.window_width.unwrap_or(self.settings.window_width) as _,
236 self.window_height.unwrap_or(self.settings.window_height) as _,
237 self.vsync.unwrap_or(self.settings.vsync),
238 self.gpu_idx.unwrap_or(self.settings.gpu_idx),
239 );
240
241 render.move_camera(&self.settings);
242
243 let mut sources = SoundSources::new();
244
245 let mut cpus: Vec<CPUEmulator> = Vec::new();
246
247 let mut field_compute_pipeline = FieldComputePipeline::new(&render, &self.settings);
248 let mut slice_viewer = SliceViewer::new(&render, &self.settings);
249 let mut imgui = ImGuiRenderer::new(self.settings.clone(), &self.config_path, &render);
250 let mut trans_viewer = TransViewer::new(&render);
251
252 let mut is_initialized = false;
253 let mut is_source_update = false;
254 let mut is_running = true;
255
256 let server_th_ref = &server_th;
257 let res = event_loop.run_return(move |event, _, control_flow| {
258 cpus.iter_mut().for_each(CPUEmulator::update);
259 if cpus.iter().any(CPUEmulator::should_update) {
260 rx_buf.write().unwrap().copy_from_iter(cpus.iter().map(|c| {
261 autd3_core::RxMessage {
262 ack: c.ack(),
263 msg_id: c.msg_id(),
264 }
265 }));
266 }
267
268 match receiver.try_recv() {
269 Ok(Signal::ConfigGeometry(geometry)) => {
270 sources.clear();
271 cpus.clear();
272
273 let devices = Vec::<_>::from_msg(&geometry);
274 devices.iter().for_each(|autd3| {
275 autd3.get_transducers(0).iter().for_each(|(_, p, r)| {
276 sources.add(
277 to_gl_pos(Vector3::new(p.x as _, p.y as _, p.z as _)),
278 to_gl_rot(Quaternion::new(r.w as _, r.i as _, r.j as _, r.k as _)),
279 Drive::new(1.0, 0.0, 1.0, 40e3, self.settings.sound_speed),
280 1.0,
281 );
282 });
283 });
284
285 cpus = (0..sources.len() / AUTD3::NUM_TRANS_IN_UNIT)
286 .map(|i| CPUEmulator::new(i, AUTD3::NUM_TRANS_IN_UNIT))
287 .collect();
288
289 *rx_buf.write().unwrap() = autd3_core::RxDatagram::new(devices.len());
290
291 field_compute_pipeline.init(&render, &sources);
292 trans_viewer.init(&render, &sources);
293 slice_viewer.init(&self.settings);
294 imgui.init(devices.len());
295
296 is_initialized = true;
297 }
298 Ok(Signal::Send(raw)) => {
299 let tx = TxDatagram::from_msg(&raw);
300 cpus.iter_mut().for_each(|cpu| {
301 cpu.send(&tx);
302 });
303 rx_buf.write().unwrap().copy_from_iter(cpus.iter().map(|c| {
304 autd3_core::RxMessage {
305 ack: c.ack(),
306 msg_id: c.msg_id(),
307 }
308 }));
309
310 is_source_update = true;
311 }
312 Ok(Signal::Close) => {
313 is_initialized = false;
314 sources.clear();
315 cpus.clear();
316 }
317 Err(TryRecvError::Empty) => {}
318 _ => {}
319 }
320
321 match event {
322 Event::WindowEvent {
323 event: WindowEvent::CloseRequested,
324 ..
325 } => {
326 is_running = false;
327 *control_flow = ControlFlow::Exit;
328 }
329 Event::WindowEvent {
330 event: WindowEvent::Resized(..),
331 window_id,
332 } if window_id == render.window().id() => {
333 render.resize();
334 imgui.resized(render.window(), &event);
335 }
336 Event::WindowEvent {
337 event:
338 WindowEvent::ScaleFactorChanged {
339 scale_factor,
340 new_inner_size,
341 },
342 window_id,
343 } if window_id == render.window().id() => {
344 *new_inner_size = render
345 .window()
346 .inner_size()
347 .to_logical::<u32>(render.window().scale_factor())
348 .to_physical(scale_factor);
349 render.resize();
350 let event_imgui: Event<'_, ()> = Event::WindowEvent {
351 window_id,
352 event: WindowEvent::ScaleFactorChanged {
353 scale_factor,
354 new_inner_size,
355 },
356 };
357 imgui.resized(render.window(), &event_imgui);
358 }
359 Event::MainEventsCleared => {
360 imgui.prepare_frame(render.window());
361 render.window().request_redraw();
362 }
363 Event::NewEvents(_) => {
364 imgui.update_delta_time();
365 render.window().request_redraw();
366 }
367 Event::RedrawRequested(_) => {
368 let before_pipeline_future = match render.start_frame() {
369 Err(e) => {
370 eprintln!("{}", e);
371 return;
372 }
373 Ok(future) => future,
374 };
375 let after_future = {
376 let framebuffer = render.frame_buffer();
377
378 let mut builder = AutoCommandBufferBuilder::primary(
379 render.command_buffer_allocator(),
380 render.queue().queue_family_index(),
381 CommandBufferUsage::OneTimeSubmit,
382 )
383 .unwrap();
384
385 let clear_values = vec![
386 Some(self.settings.background.into()),
387 Some(1f32.into()),
388 None,
389 ];
390 builder
391 .begin_render_pass(
392 RenderPassBeginInfo {
393 clear_values,
394 ..RenderPassBeginInfo::framebuffer(framebuffer)
395 },
396 SubpassContents::Inline,
397 )
398 .unwrap()
399 .set_viewport(0, [render.viewport()]);
400
401 if is_initialized {
402 render.move_camera(&self.settings);
403 let view = render.get_view();
404 let proj = render.get_projection(&self.settings);
405 let slice_model = slice_viewer.model();
406 trans_viewer.render(view, proj, &mut builder);
407 slice_viewer.render(&render, view, proj, &self.settings, &mut builder);
408 builder.end_render_pass().unwrap();
409
410 let mut update_flag = imgui.update(
411 &mut cpus,
412 &mut sources,
413 &render,
414 &mut builder,
415 &mut self.settings,
416 );
417 if is_source_update {
418 update_flag.set(UpdateFlag::UPDATE_SOURCE_DRIVE, true);
419 is_source_update = false;
420 }
421
422 if update_flag.contains(UpdateFlag::UPDATE_SOURCE_DRIVE) {
423 cpus.iter().for_each(|cpu| {
424 let cycles = cpu.fpga().cycles();
425 let drives = cpu.fpga().duties_and_phases(imgui.stm_idx());
426 let m = if self.settings.mod_enable {
427 cpu.fpga().modulation_at(imgui.mod_idx()) as f32 / 255.
428 } else {
429 1.
430 };
431 sources
432 .drives_mut()
433 .skip(cpu.id() * AUTD3::NUM_TRANS_IN_UNIT)
434 .take(AUTD3::NUM_TRANS_IN_UNIT)
435 .enumerate()
436 .for_each(|(i, d)| {
437 d.amp = (PI * drives[i].0 as f32 * m
438 / cycles[i] as f32)
439 .sin();
440 d.phase =
441 2. * PI * drives[i].1 as f32 / cycles[i] as f32;
442 d.set_wave_number(
443 FPGA_CLK_FREQ as f32 / cycles[i] as f32,
444 self.settings.sound_speed,
445 );
446 });
447 });
448 }
449
450 field_compute_pipeline.update(
451 &render,
452 &sources,
453 &self.settings,
454 &update_flag,
455 );
456 slice_viewer.update(&render, &self.settings, &update_flag);
457 trans_viewer.update(&sources, &update_flag);
458
459 let command_buffer = builder.build().unwrap();
460
461 let field_image = slice_viewer.field_image_view();
462
463 if update_flag.contains(UpdateFlag::SAVE_IMAGE) {
464 let image_buffer_content = field_image.read().unwrap();
465 let img_x = (self.settings.slice_width
466 / self.settings.slice_pixel_size)
467 as u32;
468 let img_y = (self.settings.slice_height
469 / self.settings.slice_pixel_size)
470 as u32;
471 let mut img_buf = image::ImageBuffer::new(img_x, img_y);
472 img_buf
473 .enumerate_pixels_mut()
474 .zip(image_buffer_content.iter())
475 .for_each(|((_, _, pixel), [r, g, b, a])| {
476 let r = (r * 255.0) as u8;
477 let g = (g * 255.0) as u8;
478 let b = (b * 255.0) as u8;
479 let a = (a * 255.0) as u8;
480 *pixel = image::Rgba([r, g, b, a]);
481 });
482 image::imageops::flip_vertical(&img_buf)
483 .save(&self.settings.image_save_path)
484 .unwrap();
485 }
486
487 let config = Config {
488 source_num: sources.len() as _,
489 color_scale: self.settings.slice_color_scale,
490 width: (self.settings.slice_width / self.settings.slice_pixel_size)
491 as _,
492 height: (self.settings.slice_height
493 / self.settings.slice_pixel_size)
494 as _,
495 pixel_size: self.settings.slice_pixel_size as _,
496 scale: SCALE,
497 model: slice_model.into(),
498 ..Default::default()
499 };
500 let after_compute = field_compute_pipeline
501 .compute(&render, config, field_image, &self.settings)
502 .join(before_pipeline_future);
503 let future = after_compute
504 .then_execute(render.queue(), command_buffer)
505 .unwrap();
506
507 future.boxed()
508 } else {
509 builder.end_render_pass().unwrap();
510
511 imgui.waiting(&render, &mut builder);
512
513 let command_buffer = builder.build().unwrap();
514
515 let future = before_pipeline_future
516 .then_execute(render.queue(), command_buffer)
517 .unwrap();
518
519 future.boxed()
520 }
521 };
522
523 render.finish_frame(after_future);
524 }
525 event => {
526 imgui.handle_event(render.window(), &event);
527 }
528 }
529
530 if server_th_ref.is_finished() || !is_running {
531 spdlog::default_logger().flush();
532
533 *control_flow = ControlFlow::Exit;
534 }
535 });
536
537 let _ = shutdown.send(());
538 if let Err(e) = server_th.join().unwrap() {
539 match e.source() {
540 Some(e) => spdlog::error!("Server error: {}", e),
541 None => spdlog::error!("Server error: {}", e),
542 }
543 }
544
545 res
546 }
547}