2020-02-09 05:32:56 +01:00
|
|
|
mod controls;
|
|
|
|
|
mod scene;
|
|
|
|
|
|
|
|
|
|
use controls::Controls;
|
|
|
|
|
use scene::Scene;
|
|
|
|
|
|
2020-05-21 04:54:26 +02:00
|
|
|
use iced_wgpu::{wgpu, Backend, Renderer, Settings, Viewport};
|
2021-03-10 01:59:02 +01:00
|
|
|
use iced_winit::{conversion, futures, program, winit, Clipboard, Debug, Size};
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-08-27 14:55:41 +02:00
|
|
|
use futures::task::SpawnExt;
|
2020-02-09 05:32:56 +01:00
|
|
|
use winit::{
|
2020-06-23 06:44:34 +02:00
|
|
|
dpi::PhysicalPosition,
|
2020-03-09 22:35:25 +01:00
|
|
|
event::{Event, ModifiersState, WindowEvent},
|
2020-02-09 05:32:56 +01:00
|
|
|
event_loop::{ControlFlow, EventLoop},
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
pub fn main() {
|
|
|
|
|
env_logger::init();
|
|
|
|
|
|
|
|
|
|
// Initialize winit
|
|
|
|
|
let event_loop = EventLoop::new();
|
|
|
|
|
let window = winit::window::Window::new(&event_loop).unwrap();
|
2020-05-20 20:28:35 +02:00
|
|
|
|
|
|
|
|
let physical_size = window.inner_size();
|
|
|
|
|
let mut viewport = Viewport::with_physical_size(
|
|
|
|
|
Size::new(physical_size.width, physical_size.height),
|
|
|
|
|
window.scale_factor(),
|
|
|
|
|
);
|
2020-06-23 06:44:34 +02:00
|
|
|
let mut cursor_position = PhysicalPosition::new(-1.0, -1.0);
|
2020-02-09 05:32:56 +01:00
|
|
|
let mut modifiers = ModifiersState::default();
|
2021-03-10 01:59:02 +01:00
|
|
|
let mut clipboard = Clipboard::connect(&window);
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-05-21 04:54:26 +02:00
|
|
|
// Initialize wgpu
|
2021-08-19 03:06:35 +02:00
|
|
|
let instance = wgpu::Instance::new(wgpu::Backends::PRIMARY);
|
2020-08-27 14:55:41 +02:00
|
|
|
let surface = unsafe { instance.create_surface(&window) };
|
|
|
|
|
|
2021-08-01 20:38:34 +02:00
|
|
|
let (format, (mut device, queue)) = futures::executor::block_on(async {
|
2020-08-27 14:55:41 +02:00
|
|
|
let adapter = instance
|
|
|
|
|
.request_adapter(&wgpu::RequestAdapterOptions {
|
2021-02-03 22:38:45 +01:00
|
|
|
power_preference: wgpu::PowerPreference::HighPerformance,
|
2020-04-07 05:48:21 +02:00
|
|
|
compatible_surface: Some(&surface),
|
2021-10-13 19:40:29 +02:00
|
|
|
force_fallback_adapter: false,
|
2020-08-27 14:55:41 +02:00
|
|
|
})
|
|
|
|
|
.await
|
|
|
|
|
.expect("Request adapter");
|
2020-04-07 05:48:21 +02:00
|
|
|
|
2021-08-01 20:38:34 +02:00
|
|
|
(
|
2021-08-19 03:06:35 +02:00
|
|
|
surface
|
|
|
|
|
.get_preferred_format(&adapter)
|
2021-08-04 18:20:25 +07:00
|
|
|
.expect("Get preferred format"),
|
2021-08-01 20:38:34 +02:00
|
|
|
adapter
|
|
|
|
|
.request_device(
|
|
|
|
|
&wgpu::DeviceDescriptor {
|
|
|
|
|
label: None,
|
|
|
|
|
features: wgpu::Features::empty(),
|
|
|
|
|
limits: wgpu::Limits::default(),
|
|
|
|
|
},
|
|
|
|
|
None,
|
|
|
|
|
)
|
|
|
|
|
.await
|
|
|
|
|
.expect("Request device"),
|
|
|
|
|
)
|
2020-04-07 05:48:21 +02:00
|
|
|
});
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2021-08-19 03:06:35 +02:00
|
|
|
{
|
2020-02-09 05:32:56 +01:00
|
|
|
let size = window.inner_size();
|
|
|
|
|
|
2021-08-19 03:06:35 +02:00
|
|
|
surface.configure(
|
|
|
|
|
&device,
|
|
|
|
|
&wgpu::SurfaceConfiguration {
|
|
|
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
2021-08-01 20:38:34 +02:00
|
|
|
format,
|
2020-05-20 20:28:35 +02:00
|
|
|
width: size.width,
|
|
|
|
|
height: size.height,
|
|
|
|
|
present_mode: wgpu::PresentMode::Mailbox,
|
|
|
|
|
},
|
|
|
|
|
)
|
2020-02-09 05:32:56 +01:00
|
|
|
};
|
|
|
|
|
let mut resized = false;
|
|
|
|
|
|
2020-08-27 14:55:41 +02:00
|
|
|
// Initialize staging belt and local pool
|
|
|
|
|
let mut staging_belt = wgpu::util::StagingBelt::new(5 * 1024);
|
|
|
|
|
let mut local_pool = futures::executor::LocalPool::new();
|
|
|
|
|
|
2020-05-21 04:54:26 +02:00
|
|
|
// Initialize scene and GUI controls
|
|
|
|
|
let scene = Scene::new(&mut device);
|
|
|
|
|
let controls = Controls::new();
|
|
|
|
|
|
2020-02-09 05:32:56 +01:00
|
|
|
// Initialize iced
|
2020-05-21 04:54:26 +02:00
|
|
|
let mut debug = Debug::new();
|
2020-05-19 17:15:44 +02:00
|
|
|
let mut renderer =
|
2021-08-01 20:38:34 +02:00
|
|
|
Renderer::new(Backend::new(&mut device, Settings::default(), format));
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-05-21 04:54:26 +02:00
|
|
|
let mut state = program::State::new(
|
|
|
|
|
controls,
|
|
|
|
|
viewport.logical_size(),
|
|
|
|
|
&mut renderer,
|
|
|
|
|
&mut debug,
|
|
|
|
|
);
|
2020-02-09 05:32:56 +01:00
|
|
|
|
|
|
|
|
// Run event loop
|
|
|
|
|
event_loop.run(move |event, _, control_flow| {
|
|
|
|
|
// You should change this if you want to render continuosly
|
|
|
|
|
*control_flow = ControlFlow::Wait;
|
|
|
|
|
|
|
|
|
|
match event {
|
|
|
|
|
Event::WindowEvent { event, .. } => {
|
|
|
|
|
match event {
|
2020-06-23 06:44:34 +02:00
|
|
|
WindowEvent::CursorMoved { position, .. } => {
|
|
|
|
|
cursor_position = position;
|
|
|
|
|
}
|
2020-03-09 22:35:25 +01:00
|
|
|
WindowEvent::ModifiersChanged(new_modifiers) => {
|
|
|
|
|
modifiers = new_modifiers;
|
|
|
|
|
}
|
2020-02-09 05:32:56 +01:00
|
|
|
WindowEvent::Resized(new_size) => {
|
2020-05-20 20:28:35 +02:00
|
|
|
viewport = Viewport::with_physical_size(
|
|
|
|
|
Size::new(new_size.width, new_size.height),
|
|
|
|
|
window.scale_factor(),
|
|
|
|
|
);
|
|
|
|
|
|
2020-02-09 05:32:56 +01:00
|
|
|
resized = true;
|
|
|
|
|
}
|
|
|
|
|
WindowEvent::CloseRequested => {
|
|
|
|
|
*control_flow = ControlFlow::Exit;
|
|
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Map window event to iced event
|
|
|
|
|
if let Some(event) = iced_winit::conversion::window_event(
|
2020-03-27 22:02:23 +01:00
|
|
|
&event,
|
2020-02-09 05:32:56 +01:00
|
|
|
window.scale_factor(),
|
|
|
|
|
modifiers,
|
|
|
|
|
) {
|
2020-05-21 04:54:26 +02:00
|
|
|
state.queue_event(event);
|
2020-02-09 05:32:56 +01:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
Event::MainEventsCleared => {
|
2020-06-09 15:45:57 +02:00
|
|
|
// If there are events pending
|
|
|
|
|
if !state.is_queue_empty() {
|
|
|
|
|
// We update iced
|
|
|
|
|
let _ = state.update(
|
|
|
|
|
viewport.logical_size(),
|
2020-06-23 06:44:34 +02:00
|
|
|
conversion::cursor_position(
|
|
|
|
|
cursor_position,
|
|
|
|
|
viewport.scale_factor(),
|
|
|
|
|
),
|
2020-06-09 15:45:57 +02:00
|
|
|
&mut renderer,
|
2021-03-10 01:59:02 +01:00
|
|
|
&mut clipboard,
|
2020-06-09 15:45:57 +02:00
|
|
|
&mut debug,
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// and request a redraw
|
|
|
|
|
window.request_redraw();
|
|
|
|
|
}
|
2020-02-09 05:32:56 +01:00
|
|
|
}
|
|
|
|
|
Event::RedrawRequested(_) => {
|
|
|
|
|
if resized {
|
|
|
|
|
let size = window.inner_size();
|
|
|
|
|
|
2021-08-19 03:06:35 +02:00
|
|
|
surface.configure(
|
|
|
|
|
&device,
|
|
|
|
|
&wgpu::SurfaceConfiguration {
|
|
|
|
|
usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
|
2020-05-20 20:28:35 +02:00
|
|
|
format: format,
|
|
|
|
|
width: size.width,
|
|
|
|
|
height: size.height,
|
|
|
|
|
present_mode: wgpu::PresentMode::Mailbox,
|
|
|
|
|
},
|
2020-02-09 05:32:56 +01:00
|
|
|
);
|
2020-06-02 16:48:55 -04:00
|
|
|
|
2020-06-02 16:40:46 -04:00
|
|
|
resized = false;
|
2020-02-09 05:32:56 +01:00
|
|
|
}
|
|
|
|
|
|
2021-10-13 19:40:29 +02:00
|
|
|
match surface.get_current_texture() {
|
2020-12-16 10:03:51 -06:00
|
|
|
Ok(frame) => {
|
|
|
|
|
let mut encoder = device.create_command_encoder(
|
|
|
|
|
&wgpu::CommandEncoderDescriptor { label: None },
|
|
|
|
|
);
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
let program = state.program();
|
|
|
|
|
|
2021-10-13 19:40:29 +02:00
|
|
|
let view = frame.texture.create_view(&wgpu::TextureViewDescriptor::default());
|
2021-08-19 03:06:35 +02:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
{
|
|
|
|
|
// We clear the frame
|
|
|
|
|
let mut render_pass = scene.clear(
|
2021-08-19 03:06:35 +02:00
|
|
|
&view,
|
2020-12-16 10:03:51 -06:00
|
|
|
&mut encoder,
|
|
|
|
|
program.background_color(),
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
// Draw the scene
|
|
|
|
|
scene.draw(&mut render_pass);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// And then iced on top
|
2021-11-05 15:38:27 +07:00
|
|
|
renderer.with_primitives(|backend, primitive| {
|
2021-10-14 16:07:22 +07:00
|
|
|
backend.present(
|
|
|
|
|
&mut device,
|
|
|
|
|
&mut staging_belt,
|
|
|
|
|
&mut encoder,
|
|
|
|
|
&view,
|
|
|
|
|
primitive,
|
|
|
|
|
&viewport,
|
|
|
|
|
&debug.overlay(),
|
|
|
|
|
);
|
|
|
|
|
});
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
// Then we submit the work
|
|
|
|
|
staging_belt.finish();
|
|
|
|
|
queue.submit(Some(encoder.finish()));
|
2021-10-13 19:40:29 +02:00
|
|
|
frame.present();
|
2020-05-21 04:54:26 +02:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
// Update the mouse cursor
|
2021-10-31 16:36:34 +07:00
|
|
|
window.set_cursor_icon(
|
|
|
|
|
iced_winit::conversion::mouse_interaction(
|
|
|
|
|
state.mouse_interaction(),
|
|
|
|
|
),
|
|
|
|
|
);
|
2020-02-09 05:32:56 +01:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
// And recall staging buffers
|
|
|
|
|
local_pool
|
|
|
|
|
.spawner()
|
|
|
|
|
.spawn(staging_belt.recall())
|
|
|
|
|
.expect("Recall staging buffers");
|
2020-06-03 22:01:28 +09:00
|
|
|
|
2020-12-16 10:03:51 -06:00
|
|
|
local_pool.run_until_stalled();
|
|
|
|
|
}
|
|
|
|
|
Err(error) => match error {
|
2021-08-19 03:06:35 +02:00
|
|
|
wgpu::SurfaceError::OutOfMemory => {
|
2021-07-22 13:08:13 -05:00
|
|
|
panic!("Swapchain error: {}. Rendering cannot continue.", error)
|
|
|
|
|
}
|
|
|
|
|
_ => {
|
2020-12-16 10:03:51 -06:00
|
|
|
// Try rendering again next frame.
|
|
|
|
|
window.request_redraw();
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
}
|
2020-02-09 05:32:56 +01:00
|
|
|
}
|
|
|
|
|
_ => {}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
}
|