wgpu basics part 2
This commit is contained in:
parent
6d003d2c98
commit
cbcaab8a10
|
@ -22,7 +22,10 @@ wasm-logger = "0.2"
|
|||
serde-wasm-bindgen = "0.6"
|
||||
chrono = "0.4"
|
||||
itertools = "0.11"
|
||||
winit = "0.29"
|
||||
winit = { version = "0.29", features = ["rwh_05"], default-features = false }
|
||||
wgpu = { version = "0.18", features = ["webgl"] }
|
||||
raw-window-handle = "0.5"
|
||||
wasm-bindgen-futures = "0.4"
|
||||
|
||||
[dependencies.js-sys]
|
||||
version = "0.3"
|
||||
|
|
|
@ -10,9 +10,10 @@ pub mod colors;
|
|||
use std::io::Cursor;
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use js_sys::Uint8Array;
|
||||
use log::{debug, info};
|
||||
use log::{debug, error, info};
|
||||
use wasm_bindgen::prelude::*;
|
||||
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
|
||||
use wgpu::SurfaceError;
|
||||
use winit::dpi::PhysicalSize;
|
||||
use winit::event::{ElementState, Event, WindowEvent};
|
||||
use winit::event::WindowEvent::KeyboardInput;
|
||||
|
@ -23,7 +24,8 @@ use winit::platform::web::{WindowExtWebSys, EventLoopExtWebSys};
|
|||
use crate::command::{exec, should_newline};
|
||||
use crate::mode::Mode;
|
||||
use crate::mode::Mode::Reflectivity;
|
||||
use crate::scope::{Preferences, RenderState, ScopeState};
|
||||
use crate::scope::{Preferences, ScopeState, WgpuState};
|
||||
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
|
@ -35,7 +37,7 @@ extern "C" {
|
|||
pub struct AbiScopeState(ScopeState);
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn __nxrd_browser_init() -> AbiScopeState {
|
||||
pub async fn __nxrd_browser_init(w: u32, h: u32) -> AbiScopeState {
|
||||
wasm_logger::init(wasm_logger::Config::new(log::Level::Debug));
|
||||
utils::set_panic_hook();
|
||||
|
||||
|
@ -44,7 +46,8 @@ pub fn __nxrd_browser_init() -> AbiScopeState {
|
|||
let event_loop = EventLoop::new().expect("event loop creation failed");
|
||||
let window = WindowBuilder::new().build(&event_loop).unwrap();
|
||||
|
||||
window.set_min_inner_size(Some(PhysicalSize::new(450, 400)));
|
||||
window.set_min_inner_size(Some(PhysicalSize::new(w, h)));
|
||||
|
||||
|
||||
web_sys::window()
|
||||
.and_then(|win| win.document())
|
||||
|
@ -57,6 +60,9 @@ pub fn __nxrd_browser_init() -> AbiScopeState {
|
|||
})
|
||||
.expect("Couldn't append canvas to document body.");
|
||||
|
||||
let mut render_state = WgpuState::new(window, PhysicalSize::new(w, h)).await;
|
||||
|
||||
|
||||
// If you see an error here, your IDE is not compiling for webassembly
|
||||
event_loop.spawn(move |event: Event<_>, window: &EventLoopWindowTarget<_>| {
|
||||
match event {
|
||||
|
@ -64,14 +70,29 @@ pub fn __nxrd_browser_init() -> AbiScopeState {
|
|||
match event {
|
||||
KeyboardInput { event, .. } => {
|
||||
debug!("{:?}", event.physical_key);
|
||||
if event.physical_key == KeyCode::Escape {
|
||||
window.exit();
|
||||
}
|
||||
},
|
||||
WindowEvent::CloseRequested => { window.exit(); },
|
||||
WindowEvent::Resized(physical_size) => {
|
||||
render_state.reconfigure(*physical_size);
|
||||
},
|
||||
WindowEvent::RedrawRequested => {
|
||||
render_state.update();
|
||||
match render_state.render() {
|
||||
Ok(_) => {},
|
||||
Err(SurfaceError::Lost) => render_state.reconfigure(render_state.size),
|
||||
Err(SurfaceError::OutOfMemory) => {
|
||||
error!("out of memory!");
|
||||
window.exit();
|
||||
},
|
||||
Err(e) => error!("transient rendering error: {}", e),
|
||||
}
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
},
|
||||
Event::AboutToWait => {
|
||||
render_state.window().request_redraw();
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,6 +1,13 @@
|
|||
use std::iter;
|
||||
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement, HtmlInputElement};
|
||||
use wgpu::{Backends, Color, CommandEncoderDescriptor, Device, Features, Instance, InstanceDescriptor, Limits, LoadOp, Operations, Queue, RenderPassColorAttachment, RenderPassDescriptor, StoreOp, Surface, SurfaceConfiguration, SurfaceError, TextureUsages, TextureViewDescriptor};
|
||||
use winit::dpi::PhysicalSize;
|
||||
use winit::event::WindowEvent;
|
||||
use raw_window_handle::HasRawDisplayHandle;
|
||||
use winit::window::Window;
|
||||
use nexrad2::Nexrad2Chunk;
|
||||
use crate::mode::Mode;
|
||||
use wgpu::DeviceDescriptor;
|
||||
|
||||
pub struct ScopeState {
|
||||
pub ar2: Option<Nexrad2Chunk>,
|
||||
|
@ -16,11 +23,132 @@ pub struct ScopeState {
|
|||
pub show_ui: bool
|
||||
}
|
||||
|
||||
pub struct RenderState {
|
||||
pub canvas: HtmlCanvasElement,
|
||||
pub context: CanvasRenderingContext2d
|
||||
pub struct WgpuState {
|
||||
pub surface: Surface,
|
||||
pub device: Device,
|
||||
pub queue: Queue,
|
||||
pub surface_config: SurfaceConfiguration,
|
||||
pub size: PhysicalSize<u32>,
|
||||
pub window: Window
|
||||
}
|
||||
|
||||
impl WgpuState {
|
||||
pub async fn new(window: Window, size: PhysicalSize<u32>) -> Self {
|
||||
let instance = Instance::new(InstanceDescriptor {
|
||||
backends: Backends::all(),
|
||||
flags: Default::default(),
|
||||
dx12_shader_compiler: Default::default(),
|
||||
gles_minor_version: Default::default(),
|
||||
});
|
||||
let surface = unsafe {
|
||||
instance.create_surface(&window).unwrap()
|
||||
};
|
||||
|
||||
let adapter = instance.request_adapter(
|
||||
&wgpu::RequestAdapterOptions {
|
||||
power_preference: wgpu::PowerPreference::default(),
|
||||
compatible_surface: Some(&surface),
|
||||
force_fallback_adapter: false,
|
||||
},
|
||||
).await.unwrap();
|
||||
|
||||
let (device, queue) = adapter.request_device(
|
||||
&DeviceDescriptor {
|
||||
features: Features::empty(),
|
||||
limits: Limits::downlevel_webgl2_defaults(),
|
||||
label: None,
|
||||
},
|
||||
None, // Trace path
|
||||
).await.unwrap();
|
||||
|
||||
let surface_capabilities = surface.get_capabilities(&adapter);
|
||||
|
||||
let surface_format = surface_capabilities.formats.iter()
|
||||
.copied()
|
||||
.find(|f| f.is_srgb())
|
||||
.unwrap_or(surface_capabilities.formats[0]);
|
||||
|
||||
let surface_config = SurfaceConfiguration {
|
||||
usage: TextureUsages::RENDER_ATTACHMENT,
|
||||
format: surface_format,
|
||||
width: size.width,
|
||||
height: size.height,
|
||||
present_mode: surface_capabilities.present_modes[0],
|
||||
alpha_mode: surface_capabilities.alpha_modes[0],
|
||||
view_formats: vec![],
|
||||
};
|
||||
|
||||
surface.configure(&device, &surface_config);
|
||||
|
||||
Self {
|
||||
window,
|
||||
surface,
|
||||
device,
|
||||
queue,
|
||||
surface_config,
|
||||
size
|
||||
}
|
||||
}
|
||||
|
||||
pub fn window(&self) -> &Window {
|
||||
&self.window
|
||||
}
|
||||
|
||||
pub fn reconfigure(&mut self, new_size: PhysicalSize<u32>) {
|
||||
if new_size.width > 0 && new_size.height > 0 {
|
||||
self.size = new_size;
|
||||
self.surface_config.width = new_size.width;
|
||||
self.surface_config.height = new_size.height;
|
||||
self.surface.configure(&self.device, &self.surface_config);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn input(&mut self, event: &WindowEvent) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
pub fn update(&mut self) {
|
||||
|
||||
}
|
||||
|
||||
pub fn render(&mut self) -> Result<(), SurfaceError> {
|
||||
let output = self.surface.get_current_texture()?;
|
||||
let view = output.texture.create_view(&TextureViewDescriptor::default());
|
||||
let mut encoder = self.device.create_command_encoder(&CommandEncoderDescriptor {
|
||||
label: Some("Render Encoder"),
|
||||
});
|
||||
|
||||
// LOCK BLOCK
|
||||
{
|
||||
let render_pass = encoder.begin_render_pass(&RenderPassDescriptor {
|
||||
label: Some("Render Pass"),
|
||||
color_attachments: &[Some(RenderPassColorAttachment {
|
||||
view: &view,
|
||||
resolve_target: None,
|
||||
ops: Operations {
|
||||
load: LoadOp::Clear(Color {
|
||||
r: 0.1,
|
||||
g: 0.2,
|
||||
b: 0.3,
|
||||
a: 1.0,
|
||||
}),
|
||||
store: StoreOp::Store,
|
||||
},
|
||||
})],
|
||||
depth_stencil_attachment: None,
|
||||
timestamp_writes: None,
|
||||
occlusion_query_set: None,
|
||||
});
|
||||
}
|
||||
|
||||
self.queue.submit(iter::once(encoder.finish()));
|
||||
output.present();
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
pub struct Preferences {
|
||||
pub fcs: usize
|
||||
}
|
|
@ -14,9 +14,6 @@
|
|||
}
|
||||
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
image-rendering: pixelated;
|
||||
z-index: 10000;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import * as wasm from "./wasm/nexrad_browser.js";
|
||||
await wasm.default();
|
||||
let global_context = wasm.__nxrd_browser_init();
|
||||
let global_context = wasm.__nxrd_browser_init(window.innerWidth, window.innerHeight);
|
||||
/*
|
||||
function rescaleCanvas(canvas, ctx) {
|
||||
var dpr = window.devicePixelRatio || 1;
|
||||
|
|
Loading…
Reference in New Issue