Skip to content

Commit e13f8c8

Browse files
committed
Add WebGPU renderer with Canvas 2D fallback for performance
1 parent 4d7fbd8 commit e13f8c8

6 files changed

Lines changed: 401 additions & 10 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,13 @@ tempfile = "3.8"
3535
# WebAssembly support
3636
wasm-bindgen = "0.2"
3737
wasm-bindgen-rayon = "1.2"
38+
wasm-bindgen-futures = "0.4"
3839
web-sys = { version = "0.3", features = [
3940
"HtmlCanvasElement",
4041
"CanvasRenderingContext2d",
42+
"Window",
43+
"Document",
44+
"Element",
4145
] }
4246
serde-wasm-bindgen = "0.6"
4347
console_error_panic_hook = "0.1"

src/lib.rs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ struct EntityData {
2929
pub struct WebSimulation {
3030
simulation: simulation::Simulation,
3131
config: config::SimulationConfig,
32+
entity_buffer: Vec<f32>, // Reusable buffer for entity data
3233
}
3334

3435
#[wasm_bindgen]
@@ -40,7 +41,11 @@ impl WebSimulation {
4041

4142
let simulation = simulation::Simulation::new_with_config(world_size, config.clone());
4243

43-
Ok(WebSimulation { simulation, config })
44+
Ok(WebSimulation {
45+
simulation,
46+
config,
47+
entity_buffer: Vec::with_capacity(60000), // 10000 entities * 6 floats
48+
})
4449
}
4550

4651
pub fn update(&mut self) {
@@ -63,6 +68,27 @@ impl WebSimulation {
6368
serde_wasm_bindgen::to_value(&entities).unwrap_or(JsValue::NULL)
6469
}
6570

71+
/// Update entity buffer and return pointer for WebGPU renderer
72+
pub fn update_entity_buffer(&mut self) -> *const f32 {
73+
let entity_tuples = self.simulation.get_entities();
74+
self.entity_buffer.clear();
75+
76+
for (x, y, radius, r, g, b) in entity_tuples {
77+
self.entity_buffer.push(x);
78+
self.entity_buffer.push(y);
79+
self.entity_buffer.push(radius);
80+
self.entity_buffer.push(r);
81+
self.entity_buffer.push(g);
82+
self.entity_buffer.push(b);
83+
}
84+
85+
self.entity_buffer.as_ptr()
86+
}
87+
88+
pub fn entity_count(&self) -> u32 {
89+
(self.entity_buffer.len() / 6) as u32
90+
}
91+
6692
pub fn get_stats(&self) -> JsValue {
6793
let stats = stats::SimulationStats::from_world(
6894
self.simulation.world(),

src/web/mod.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
mod webgpu;
2+
pub use webgpu::WebGpuRenderer;
3+
14
use serde::{Deserialize, Serialize};
25
use wasm_bindgen::prelude::*;
36
use web_sys::{CanvasRenderingContext2d, HtmlCanvasElement};
@@ -12,6 +15,7 @@ struct EntityData {
1215
b: f32,
1316
}
1417

18+
/// Legacy Canvas 2D renderer (fallback for browsers without WebGPU)
1519
#[wasm_bindgen]
1620
pub struct WebRenderer {
1721
ctx: CanvasRenderingContext2d,
@@ -43,24 +47,20 @@ impl WebRenderer {
4347

4448
#[allow(deprecated)]
4549
pub fn render(&self, entities: &JsValue) -> Result<(), JsValue> {
46-
// Parse entities from JS
4750
let entities: Vec<EntityData> = serde_wasm_bindgen::from_value(entities.clone())?;
4851

49-
// Clear canvas
5052
self.ctx
5153
.clear_rect(0.0, 0.0, self.width as f64, self.height as f64);
5254

53-
// Calculate center offset to center the simulation world
5455
let center_x = self.width as f64 / 2.0;
5556
let center_y = self.height as f64 / 2.0;
5657

57-
// Render each entity
5858
for entity in entities {
5959
self.ctx.begin_path();
6060
self.ctx.arc(
6161
center_x + entity.x as f64,
6262
center_y + entity.y as f64,
63-
(entity.radius * 0.1) as f64, // Make entities 10x smaller
63+
(entity.radius * 0.1) as f64,
6464
0.0,
6565
2.0 * std::f64::consts::PI,
6666
)?;

0 commit comments

Comments
 (0)