rust/hwrunner/src/main.rs
changeset 15776 ec85fdf82942
parent 15766 19ad3fe48ea6
child 15777 2b3f8af6f647
equal deleted inserted replaced
15775:95402fa4e191 15776:ec85fdf82942
       
     1 use std::time::Duration;
       
     2 
       
     3 use futures::executor::block_on;
     1 use glutin::{
     4 use glutin::{
     2     dpi, ContextTrait, DeviceEvent, ElementState, Event, EventsLoop, GlProfile, GlRequest,
     5     dpi, ContextTrait, DeviceEvent, ElementState, Event, EventsLoop, GlProfile, GlRequest,
     3     MouseButton, MouseScrollDelta, WindowEvent, WindowedContext,
     6     MouseButton, MouseScrollDelta, Window, WindowBuilder, WindowEvent, WindowedContext,
     4 };
     7 };
     5 
       
     6 use hedgewars_engine::instance::EngineInstance;
     8 use hedgewars_engine::instance::EngineInstance;
     7 
       
     8 use integral_geometry::Point;
     9 use integral_geometry::Point;
     9 use std::time::Duration;
    10 use std::error::Error;
    10 
    11 use wgpu::{
    11 fn init(event_loop: &EventsLoop, size: dpi::LogicalSize) -> WindowedContext {
    12     Adapter, BackendBit, Color, CommandEncoderDescriptor, Device, DeviceDescriptor, Features,
    12     use glutin::{ContextBuilder, WindowBuilder};
    13     LoadOp, Operations, PowerPreference, PresentMode, Queue, RenderPassColorAttachmentDescriptor,
    13 
    14     RenderPassDescriptor, RequestAdapterOptions, Surface, SwapChain, SwapChainDescriptor,
    14     let window = WindowBuilder::new()
    15     TextureFormat, TextureUsage,
       
    16 };
       
    17 
       
    18 type HwGlRendererContext = WindowedContext;
       
    19 
       
    20 struct HwWgpuRenderingContext {
       
    21     window: Window,
       
    22     surface: Surface,
       
    23     adapter: Adapter,
       
    24     device: Device,
       
    25     queue: Queue,
       
    26     swap_chain: SwapChain,
       
    27 }
       
    28 
       
    29 enum HwRendererContext {
       
    30     Gl(HwGlRendererContext),
       
    31     Wgpu(HwWgpuRenderingContext),
       
    32 }
       
    33 
       
    34 struct ErrorStub;
       
    35 
       
    36 impl<T: Error> From<T> for ErrorStub {
       
    37     fn from(_: T) -> Self {
       
    38         ErrorStub
       
    39     }
       
    40 }
       
    41 
       
    42 impl HwRendererContext {
       
    43     pub fn window(&self) -> &Window {
       
    44         match self {
       
    45             HwRendererContext::Gl(gl) => &gl.window(),
       
    46             HwRendererContext::Wgpu(wgpu) => &wgpu.window,
       
    47         }
       
    48     }
       
    49 
       
    50     pub fn update(&mut self, size: dpi::LogicalSize) {
       
    51         let phys = size.to_physical(self.window().get_hidpi_factor());
       
    52         match self {
       
    53             HwRendererContext::Gl(context) => unsafe {
       
    54                 gl::Viewport(0, 0, phys.width as i32, phys.height as i32);
       
    55             },
       
    56             HwRendererContext::Wgpu(context) => {
       
    57                 context.swap_chain = context.device.create_swap_chain(
       
    58                     &context.surface,
       
    59                     &SwapChainDescriptor {
       
    60                         usage: TextureUsage::OUTPUT_ATTACHMENT,
       
    61                         format: TextureFormat::Bgra8Unorm,
       
    62                         width: phys.width as u32,
       
    63                         height: phys.height as u32,
       
    64                         present_mode: PresentMode::Fifo,
       
    65                     },
       
    66                 );
       
    67             }
       
    68         }
       
    69     }
       
    70 
       
    71     pub fn present(&mut self) -> Result<(), ErrorStub> {
       
    72         match self {
       
    73             HwRendererContext::Gl(context) => context.swap_buffers()?,
       
    74             HwRendererContext::Wgpu(context) => {
       
    75                 let frame_view = &context.swap_chain.get_current_frame()?.output.view;
       
    76 
       
    77                 let mut encoder =
       
    78                     context
       
    79                         .device
       
    80                         .create_command_encoder(&CommandEncoderDescriptor {
       
    81                             label: Some("Main encoder"),
       
    82                         });
       
    83                 encoder.begin_render_pass(&RenderPassDescriptor {
       
    84                     color_attachments: &[RenderPassColorAttachmentDescriptor {
       
    85                         attachment: &frame_view,
       
    86                         resolve_target: None,
       
    87                         ops: Operations {
       
    88                             load: LoadOp::Clear(Color::BLUE),
       
    89                             store: false,
       
    90                         },
       
    91                     }],
       
    92                     depth_stencil_attachment: None,
       
    93                 });
       
    94                 let buffer = encoder.finish();
       
    95                 context.queue.submit(std::iter::once(buffer));
       
    96             }
       
    97         }
       
    98         Ok(())
       
    99     }
       
   100 }
       
   101 
       
   102 fn init_wgpu(event_loop: &EventsLoop, size: dpi::LogicalSize) -> HwWgpuRenderingContext {
       
   103     let builder = WindowBuilder::new()
    15         .with_title("hwengine")
   104         .with_title("hwengine")
    16         .with_dimensions(size);
   105         .with_dimensions(size);
    17 
   106     let window = builder.build(event_loop).unwrap();
    18     let cxt = ContextBuilder::new()
   107 
       
   108     let instance = wgpu::Instance::new(BackendBit::PRIMARY);
       
   109 
       
   110     let surface = unsafe { instance.create_surface(&window) };
       
   111 
       
   112     let adapter = block_on(instance.request_adapter(&RequestAdapterOptions {
       
   113         power_preference: PowerPreference::HighPerformance,
       
   114         compatible_surface: Some(&surface),
       
   115     }))
       
   116     .unwrap();
       
   117 
       
   118     let (device, queue) = block_on(adapter.request_device(&Default::default(), None)).unwrap();
       
   119 
       
   120     let size = window.get_inner_size().unwrap();
       
   121 
       
   122     let phys = size.to_physical(window.get_hidpi_factor());
       
   123 
       
   124     let mut swap_chain = device.create_swap_chain(
       
   125         &surface,
       
   126         &SwapChainDescriptor {
       
   127             usage: TextureUsage::OUTPUT_ATTACHMENT,
       
   128             format: TextureFormat::Bgra8Unorm,
       
   129             width: phys.width as u32,
       
   130             height: phys.height as u32,
       
   131             present_mode: PresentMode::Fifo,
       
   132         },
       
   133     );
       
   134 
       
   135     HwWgpuRenderingContext {
       
   136         window,
       
   137         surface,
       
   138         adapter,
       
   139         device,
       
   140         queue,
       
   141         swap_chain,
       
   142     }
       
   143 }
       
   144 
       
   145 fn init_gl(event_loop: &EventsLoop, size: dpi::LogicalSize) -> HwGlRendererContext {
       
   146     use glutin::ContextBuilder;
       
   147 
       
   148     let builder = WindowBuilder::new()
       
   149         .with_title("hwengine")
       
   150         .with_dimensions(size);
       
   151 
       
   152     let context = ContextBuilder::new()
    19         .with_gl(GlRequest::Latest)
   153         .with_gl(GlRequest::Latest)
    20         .with_gl_profile(GlProfile::Core)
   154         .with_gl_profile(GlProfile::Core)
    21         .build_windowed(window, &event_loop)
   155         .build_windowed(builder, &event_loop)
    22         .ok()
   156         .ok()
    23         .unwrap();
   157         .unwrap();
    24 
   158 
    25     unsafe {
   159     unsafe {
    26         cxt.make_current().unwrap();
   160         context.make_current().unwrap();
    27         gl::load_with(|ptr| cxt.get_proc_address(ptr) as *const _);
   161         gl::load_with(|ptr| context.get_proc_address(ptr) as *const _);
    28 
   162 
    29         if let Some(sz) = cxt.get_inner_size() {
   163         if let Some(sz) = context.get_inner_size() {
    30             let phys = sz.to_physical(cxt.get_hidpi_factor());
   164             let phys = sz.to_physical(context.get_hidpi_factor());
    31 
   165 
    32             gl::Viewport(0, 0, phys.width as i32, phys.height as i32);
   166             gl::Viewport(0, 0, phys.width as i32, phys.height as i32);
    33         }
   167         }
    34     }
   168     }
    35 
   169 
    36     cxt
   170     context
       
   171 }
       
   172 
       
   173 fn init(event_loop: &EventsLoop, size: dpi::LogicalSize, use_wgpu: bool) -> HwRendererContext {
       
   174     if use_wgpu {
       
   175         HwRendererContext::Wgpu(init_wgpu(event_loop, size))
       
   176     } else {
       
   177         HwRendererContext::Gl(init_gl(event_loop, size))
       
   178     }
    37 }
   179 }
    38 
   180 
    39 fn main() {
   181 fn main() {
       
   182     let use_wgpu = false;
    40     let mut event_loop = EventsLoop::new();
   183     let mut event_loop = EventsLoop::new();
    41     let (w, h) = (1024.0, 768.0);
   184     let (w, h) = (1024.0, 768.0);
    42     let window = init(&event_loop, dpi::LogicalSize::new(w, h));
   185 
       
   186     let mut context = init(&event_loop, dpi::LogicalSize::new(w, h), use_wgpu);
    43 
   187 
    44     let mut engine = EngineInstance::new();
   188     let mut engine = EngineInstance::new();
    45     engine.world.create_renderer(w as u16, h as u16);
   189     if !use_wgpu {
       
   190         engine.world.create_renderer(w as u16, h as u16);
       
   191     }
    46 
   192 
    47     let mut dragging = false;
   193     let mut dragging = false;
    48 
   194 
    49     use std::time::Instant;
   195     use std::time::Instant;
    50 
   196 
    51     let mut now = Instant::now();
   197     let mut now = Instant::now();
    52     let mut update = Instant::now();
   198     let mut update_time = Instant::now();
    53     let mut render = Instant::now();
   199     let mut render_time = Instant::now();
    54 
   200 
    55     unsafe { window.make_current().unwrap() };
       
    56     let mut is_running = true;
   201     let mut is_running = true;
    57 
   202 
    58     while is_running {
   203     while is_running {
    59         let curr = Instant::now();
   204         let current_time = Instant::now();
    60         let delta = curr - now;
   205         let delta = current_time - now;
    61         now = curr;
   206         now = current_time;
    62         let ms = delta.as_secs() as f64 * 1000.0 + delta.subsec_millis() as f64;
   207         let ms = delta.as_secs() as f64 * 1000.0 + delta.subsec_millis() as f64;
    63         window.set_title(&format!("hwengine {:.3}ms", ms));
   208         context.window().set_title(&format!("hwengine {:.3}ms", ms));
    64 
   209 
    65         if update.elapsed() > Duration::from_millis(10) {
   210         if update_time.elapsed() > Duration::from_millis(10) {
    66             update = curr;
   211             update_time = current_time;
    67             engine.world.step()
   212             engine.world.step()
    68         }
   213         }
    69 
   214 
    70         event_loop.poll_events(|event| match event {
   215         event_loop.poll_events(|event| match event {
    71             Event::WindowEvent { event, .. } => match event {
   216             Event::WindowEvent { event, .. } => match event {
    72                 WindowEvent::CloseRequested => {
   217                 WindowEvent::CloseRequested => {
    73                     is_running = false;
   218                     is_running = false;
    74                 }
   219                 }
       
   220                 WindowEvent::Resized(size) => context.update(size),
       
   221 
    75                 WindowEvent::MouseInput { button, state, .. } => {
   222                 WindowEvent::MouseInput { button, state, .. } => {
    76                     if let MouseButton::Right = button {
   223                     if let MouseButton::Right = button {
    77                         dragging = state == ElementState::Pressed;
   224                         dragging = state == ElementState::Pressed;
    78                     }
   225                     }
    79                 }
   226                 }
    80 
   227 
    81                 WindowEvent::MouseWheel { delta, .. } => {
   228                 WindowEvent::MouseWheel { delta, .. } => {
    82                     let zoom_change = match delta {
   229                     let zoom_change = match delta {
    83                         MouseScrollDelta::LineDelta(x, y) => y as f32 * 0.1f32,
   230                         MouseScrollDelta::LineDelta(x, y) => y as f32 * 0.1f32,
    84                         MouseScrollDelta::PixelDelta(delta) => {
   231                         MouseScrollDelta::PixelDelta(delta) => {
    85                             let physical = delta.to_physical(window.get_hidpi_factor());
   232                             let physical = delta.to_physical(context.window().get_hidpi_factor());
    86                             physical.y as f32 * 0.1f32
   233                             physical.y as f32 * 0.1f32
    87                         }
   234                         }
    88                     };
   235                     };
    89                     engine.world.move_camera(Point::ZERO, zoom_change);
   236                     engine.world.move_camera(Point::ZERO, zoom_change);
    90                 }
   237                 }
   101                 _ => {}
   248                 _ => {}
   102             },
   249             },
   103             _ => (),
   250             _ => (),
   104         });
   251         });
   105 
   252 
   106         if render.elapsed() > Duration::from_millis(16) {
   253         if render_time.elapsed() > Duration::from_millis(16) {
   107             render = curr;
   254             render_time = current_time;
   108             engine.render();
   255             if !use_wgpu {
   109             window.swap_buffers().unwrap();
   256                 engine.render();
   110         }
   257             }
   111     }
   258             context.present();
   112 }
   259         }
       
   260     }
       
   261 }