Fix wasm crashing on startup

This commit is contained in:
Lauri Räsänen 2023-11-05 00:16:34 +02:00
parent 7aa70cd564
commit 091bdcaa98
6 changed files with 41 additions and 15 deletions

View file

@ -7,13 +7,16 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>wgpu-renderer</title> <title>wgpu-renderer</title>
<style> <style>
body {
margin: 0;
padding: 0;
background: black;
}
canvas { canvas {
background-color: black; background-color: black;
display: block; display: block;
width: 100%; width: 100vw;
height: 100%; height: 100vh;
min-width: 4px;
min-height: 4px;
} }
#loading { #loading {
color: white; color: white;
@ -25,7 +28,7 @@
</style> </style>
</head> </head>
<body style="margin: 0; padding: 0"> <body>
<h1 id="loading">Loading...</h1> <h1 id="loading">Loading...</h1>
<script type="module"> <script type="module">
import init from "./pkg/wgpu_renderer.js"; import init from "./pkg/wgpu_renderer.js";

View file

@ -13,5 +13,5 @@ fn vs_main(
); );
let world_position = model_matrix * vec4<f32>(model.position, 1.0); let world_position = model_matrix * vec4<f32>(model.position, 1.0);
return light.matrices[light_matrix_index] * world_position; return light.matrices[light_matrix_index.value] * world_position;
} }

View file

@ -16,8 +16,15 @@ struct Light {
@group(1) @binding(0) @group(1) @binding(0)
var<uniform> light: Light; var<uniform> light: Light;
// Needs to be 16 bytes in WebGL
struct LightMatrixIndex {
value: u32,
_padding: u32,
_padding1: u32,
_padding2: u32,
}
@group(1) @binding(1) @group(1) @binding(1)
var<uniform> light_matrix_index: u32; var<uniform> light_matrix_index: LightMatrixIndex;
struct VertexInput { struct VertexInput {
@location(0) position: vec3<f32>, @location(0) position: vec3<f32>,

View file

@ -41,6 +41,14 @@ impl LightUniform {
} }
} }
#[repr(C)]
#[derive(Debug, Default, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
pub struct LightMatrixUniform {
pub value: u32,
// No DownlevelFlags::BUFFER_BINDINGS_NOT_16_BYTE_ALIGNED in WebGL
_padding: [u32; 3],
}
pub trait DrawLight<'a> { pub trait DrawLight<'a> {
fn draw_light_mesh( fn draw_light_mesh(
&mut self, &mut self,

View file

@ -2,11 +2,12 @@ use cgmath::prelude::*;
use wgpu::{InstanceDescriptor, Backends, TextureView, TextureViewDescriptor, StoreOp}; use wgpu::{InstanceDescriptor, Backends, TextureView, TextureViewDescriptor, StoreOp};
use std::default::Default; use std::default::Default;
use std::mem; use std::mem;
use std::num::NonZeroU32;
use std::time::Duration; use std::time::Duration;
use wgpu::util::DeviceExt; use wgpu::util::DeviceExt;
use winit::{event::*, window::Window}; use winit::{event::*, window::Window};
use winit::dpi::PhysicalSize;
use crate::core::light::LightMatrixUniform;
use super::camera::{Camera, CameraController, CameraUniform}; use super::camera::{Camera, CameraController, CameraUniform};
use super::instance::{Instance, InstanceRaw}; use super::instance::{Instance, InstanceRaw};
@ -44,14 +45,17 @@ pub struct State {
light_depth_bind_group: wgpu::BindGroup, light_depth_bind_group: wgpu::BindGroup,
light_depth_pass: RenderPass, light_depth_pass: RenderPass,
light_depth_texture_target_views: [TextureView; SHADOW_MAP_LAYERS as usize], light_depth_texture_target_views: [TextureView; SHADOW_MAP_LAYERS as usize],
light_matrix_uniform: u32, light_matrix_uniform: LightMatrixUniform,
light_matrix_buffer: wgpu::Buffer, light_matrix_buffer: wgpu::Buffer,
} }
impl State { impl State {
// Creating some of the wgpu types requires async code // Creating some of the wgpu types requires async code
pub async fn new(window: &Window) -> Self { pub async fn new(window: &Window) -> Self {
let size = window.inner_size(); log::info!("Creating surface");
let mut size = window.inner_size();
size.width = size.width.max(1);
size.height = size.height.max(1);
let instance = wgpu::Instance::new(InstanceDescriptor { backends: Backends::all(), ..Default::default() }); let instance = wgpu::Instance::new(InstanceDescriptor { backends: Backends::all(), ..Default::default() });
let surface = unsafe { instance.create_surface(window) }.unwrap(); let surface = unsafe { instance.create_surface(window) }.unwrap();
@ -64,7 +68,6 @@ impl State {
.await .await
.expect("failed to get adapter"); .expect("failed to get adapter");
// TODO: some feature here doesn't work on WASM
let (device, queue) = adapter let (device, queue) = adapter
.request_device( .request_device(
&wgpu::DeviceDescriptor { &wgpu::DeviceDescriptor {
@ -111,6 +114,7 @@ impl State {
contents: bytemuck::cast_slice(&[camera_uniform]), contents: bytemuck::cast_slice(&[camera_uniform]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}); });
let camera_uniform_size = mem::size_of::<CameraUniform>() as u64;
let camera_bind_group_layout = let camera_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry { entries: &[wgpu::BindGroupLayoutEntry {
@ -119,7 +123,7 @@ impl State {
ty: wgpu::BindingType::Buffer { ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform, ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false, has_dynamic_offset: false,
min_binding_size: None, min_binding_size: wgpu::BufferSize::new(camera_uniform_size),
}, },
count: None, count: None,
}], }],
@ -182,7 +186,7 @@ impl State {
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST, usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
}); });
let light_matrix_uniform = 0; let light_matrix_uniform = LightMatrixUniform::default();
let light_matrix_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor { let light_matrix_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Light Matrix UB"), label: Some("Light Matrix UB"),
contents: bytemuck::cast_slice(&[light_matrix_uniform]), contents: bytemuck::cast_slice(&[light_matrix_uniform]),
@ -190,7 +194,7 @@ impl State {
}); });
let light_uniform_size = mem::size_of::<LightUniform>() as u64; let light_uniform_size = mem::size_of::<LightUniform>() as u64;
let light_matrix_uniform_size = mem::size_of::<u32>() as u64; let light_matrix_uniform_size = mem::size_of::<LightMatrixUniform>() as u64;
let light_bind_group_layout = let light_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor { device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[ entries: &[
@ -502,7 +506,7 @@ impl State {
// render light to depth textures // render light to depth textures
for i in 0..SHADOW_MAP_LAYERS as usize { for i in 0..SHADOW_MAP_LAYERS as usize {
self.light_matrix_uniform = i as u32; self.light_matrix_uniform.value = i as u32;
self.queue.write_buffer( self.queue.write_buffer(
&self.light_matrix_buffer, &self.light_matrix_buffer,
0, 0,

View file

@ -8,6 +8,7 @@ use winit::keyboard::{KeyCode, PhysicalKey};
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
fn create_window(event_loop: &EventLoop<()>) -> winit::window::Window { fn create_window(event_loop: &EventLoop<()>) -> winit::window::Window {
log::info!("Creating window");
use winit::dpi::PhysicalSize; use winit::dpi::PhysicalSize;
WindowBuilder::new() WindowBuilder::new()
.with_inner_size(PhysicalSize::new(1280, 720)) .with_inner_size(PhysicalSize::new(1280, 720))
@ -18,6 +19,7 @@ fn create_window(event_loop: &EventLoop<()>) -> winit::window::Window {
#[cfg(not(debug_assertions))] #[cfg(not(debug_assertions))]
fn create_window(event_loop: &EventLoop<()>) -> winit::window::Window { fn create_window(event_loop: &EventLoop<()>) -> winit::window::Window {
log::info!("Creating window");
WindowBuilder::new() WindowBuilder::new()
.with_fullscreen(Some(winit::window::Fullscreen::Borderless(None))) .with_fullscreen(Some(winit::window::Fullscreen::Borderless(None)))
.with_maximized(true) .with_maximized(true)
@ -31,6 +33,7 @@ pub async fn run() {
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
{ {
log::info!("Appending canvas to document");
use winit::platform::web::WindowExtWebSys; use winit::platform::web::WindowExtWebSys;
web_sys::window() web_sys::window()
.and_then(|win| win.document()) .and_then(|win| win.document())
@ -103,6 +106,7 @@ pub async fn run() {
} }
} }
WindowEvent::Resized(physical_size) => { WindowEvent::Resized(physical_size) => {
log::info!("WindowEvent::Resized {}:{}", physical_size.width, physical_size.height);
state.resize(*physical_size); state.resize(*physical_size);
window.request_redraw(); window.request_redraw();
} }