refactor: remove dead input and readback paths

Amp-Thread-ID: https://ampcode.com/threads/T-019f9d91-77c1-7206-a60f-ed6554ce92ab

Co-authored-by: Heaust Azure <heaust.azure@gmail.com>
This commit is contained in:
Amp
2026-07-29 01:28:57 +00:00
co-authored by heaust
parent b5366d8b77
commit 2ff8a4a17b
5 changed files with 68 additions and 197 deletions
-1
View File
@@ -21,7 +21,6 @@ web-sys = { version = "0.3.77", features = [
"MouseEvent", "MouseEvent",
"PointerEvent", "PointerEvent",
"WheelEvent", "WheelEvent",
"KeyboardEvent",
"Worker", "Worker",
"DedicatedWorkerGlobalScope", "DedicatedWorkerGlobalScope",
"Event", "Event",
-16
View File
@@ -22,7 +22,6 @@ pub struct EventListeners {
pub click_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>, pub click_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>,
pub wheel_listener: Option<Closure<dyn FnMut(web_sys::WheelEvent)>>, pub wheel_listener: Option<Closure<dyn FnMut(web_sys::WheelEvent)>>,
pub contextmenu_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>, pub contextmenu_listener: Option<Closure<dyn FnMut(web_sys::MouseEvent)>>,
pub keyboard_listener: Option<Closure<dyn FnMut(web_sys::KeyboardEvent)>>,
} }
#[cfg(target_arch = "wasm32")] #[cfg(target_arch = "wasm32")]
@@ -34,7 +33,6 @@ impl EventListeners {
click_listener: None, click_listener: None,
wheel_listener: None, wheel_listener: None,
contextmenu_listener: None, contextmenu_listener: None,
keyboard_listener: None,
} }
} }
} }
@@ -153,26 +151,12 @@ pub fn setup_event_listeners(
contextmenu_listener.as_ref().unchecked_ref(), contextmenu_listener.as_ref().unchecked_ref(),
)?; )?;
let keyboard_worker_chan = worker_chan.clone();
let keyboard_listener: Closure<dyn FnMut(web_sys::KeyboardEvent)> =
Closure::new(move |event: web_sys::KeyboardEvent| {
use crate::message::KeyboardMessage;
let keyboard_event_data = KeyboardMessage::from_evt(event);
let _ = keyboard_worker_chan.send(WindowEvent::Keyboard(keyboard_event_data));
});
window
.add_event_listener_with_callback("keydown", keyboard_listener.as_ref().unchecked_ref())?;
Ok(EventListeners { Ok(EventListeners {
resize_listener: Some(resize_listener), resize_listener: Some(resize_listener),
pointer_listener: Some(pointer_listener), pointer_listener: Some(pointer_listener),
click_listener: Some(click_listener), click_listener: Some(click_listener),
wheel_listener: Some(wheel_listener), wheel_listener: Some(wheel_listener),
contextmenu_listener: Some(contextmenu_listener), contextmenu_listener: Some(contextmenu_listener),
keyboard_listener: Some(keyboard_listener),
}) })
} }
-47
View File
@@ -42,20 +42,6 @@ pub enum WindowEvent {
PointerMove(MouseMessage), PointerMove(MouseMessage),
PointerClick(MouseMessage), PointerClick(MouseMessage),
PointerWheel(WheelMessage), PointerWheel(WheelMessage),
Keyboard(KeyboardMessage),
}
// Display for WindowEvent
impl fmt::Display for WindowEvent {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
WindowEvent::Resize(msg) => write!(f, "Resize: {:?}", msg),
WindowEvent::PointerMove(msg) => write!(f, "PointerMove: {:?}", msg),
WindowEvent::PointerClick(msg) => write!(f, "PointerClick: {:?}", msg),
WindowEvent::PointerWheel(msg) => write!(f, "PointerWheel: {:?}", msg),
WindowEvent::Keyboard(msg) => write!(f, "Keyboard: {:?}", msg),
}
}
} }
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
@@ -68,10 +54,7 @@ pub struct ResizeMessage {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MouseMessage { pub struct MouseMessage {
pub scale_factor: f64, pub scale_factor: f64,
pub button: f64,
pub buttons: u16, pub buttons: u16,
pub client_x: f64,
pub client_y: f64,
pub movement_x: f64, pub movement_x: f64,
pub movement_y: f64, pub movement_y: f64,
pub offset_x: f64, pub offset_x: f64,
@@ -84,10 +67,7 @@ impl MouseMessage {
let window = web_sys::window().unwrap(); let window = web_sys::window().unwrap();
Self { Self {
scale_factor: window.device_pixel_ratio(), scale_factor: window.device_pixel_ratio(),
button: event.button() as f64,
buttons: event.buttons(), buttons: event.buttons(),
client_x: event.client_x() as f64,
client_y: event.client_y() as f64,
movement_x: event.movement_x() as f64, movement_x: event.movement_x() as f64,
movement_y: event.movement_y() as f64, movement_y: event.movement_y() as f64,
offset_x: event.offset_x() as f64, offset_x: event.offset_x() as f64,
@@ -113,33 +93,6 @@ impl WheelMessage {
} }
} }
#[derive(Debug, Clone)]
pub struct KeyboardMessage {
pub key: String,
pub code: String,
pub alt_key: bool,
pub ctrl_key: bool,
pub meta_key: bool,
pub shift_key: bool,
pub location: u32,
pub repeat: bool,
}
impl KeyboardMessage {
pub fn from_evt(event: web_sys::KeyboardEvent) -> Self {
Self {
key: event.key(),
code: event.code(),
alt_key: event.alt_key(),
ctrl_key: event.ctrl_key(),
meta_key: event.meta_key(),
shift_key: event.shift_key(),
location: event.location(),
repeat: event.repeat(),
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum DrainEventError { pub enum DrainEventError {
BorrowError(BorrowMutError), BorrowError(BorrowMutError),
+57 -10
View File
@@ -136,13 +136,14 @@ pub fn generate_wgsl(plan: &InstanceTraversalPlan) -> Result<String, String> {
fixed_index(*index, 32, "u32 bit projection")?; fixed_index(*index, 32, "u32 bit projection")?;
format!("(({} & (1u<<{}u))!=0u)", x(*value), index) format!("(({} & (1u<<{}u))!=0u)", x(*value), index)
} }
ExpressionOp::U32Construct { bits } => bits ExpressionOp::U32Construct { bits } => format!(
.iter() "({})",
bits.iter()
.enumerate() .enumerate()
.map(|(bit, id)| format!("select(0u,{}u,{})", 1u32 << bit, x(*id))) .map(|(bit, id)| format!("select(0u,{}u,{})", 1u32 << bit, x(*id)))
.collect::<Vec<_>>() .collect::<Vec<_>>()
.join("|") .join("|")
.pipe(|terms| format!("({terms})")), ),
ExpressionOp::AabbMin { aabb } => format!("{}.min", x(*aabb)), ExpressionOp::AabbMin { aabb } => format!("{}.min", x(*aabb)),
ExpressionOp::AabbMax { aabb } => format!("{}.max", x(*aabb)), ExpressionOp::AabbMax { aabb } => format!("{}.max", x(*aabb)),
ExpressionOp::FrustumCulled { local_aabb, .. } => { ExpressionOp::FrustumCulled { local_aabb, .. } => {
@@ -201,13 +202,6 @@ fn matrix_literal<const N: usize>(name: &str, columns: &[[f32; N]; N]) -> Result
.collect::<Result<Vec<_>, _>>()?; .collect::<Result<Vec<_>, _>>()?;
Ok(format!("{name}({})", values.join(","))) Ok(format!("{name}({})", values.join(",")))
} }
trait Pipe: Sized {
fn pipe<R>(self, f: impl FnOnce(Self) -> R) -> R {
f(self)
}
}
impl<T> Pipe for T {}
pub fn dispatch_count(instances: u32, pipelines: u32) -> u32 { pub fn dispatch_count(instances: u32, pipelines: u32) -> u32 {
if pipelines == 0 { if pipelines == 0 {
0 0
@@ -403,6 +397,19 @@ impl TraversalGpu {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use crate::render_graph::{Expression, ExpressionPlan, NodeOutputRef};
fn expression(semantic_type: SemanticType, op: ExpressionOp) -> Expression {
Expression {
semantic_type,
op,
origin: NodeOutputRef {
node: "test".into(),
socket: "value".into(),
},
mesh_provenance: None,
}
}
#[test] #[test]
fn pipeline_major_offsets_and_single_dispatch_are_deterministic() { fn pipeline_major_offsets_and_single_dispatch_are_deterministic() {
@@ -424,4 +431,44 @@ mod tests {
assert!(fixed_index(3, 3, "vector projection").is_err()); assert!(fixed_index(3, 3, "vector projection").is_err());
assert_eq!(wgsl_type(&SemanticType::Mat4).unwrap(), "mat4x4<f32>"); assert_eq!(wgsl_type(&SemanticType::Mat4).unwrap(), "mat4x4<f32>");
} }
#[test]
fn u32_construct_wgsl_is_parenthesized() {
let plan = InstanceTraversalPlan {
mesh: 0,
expressions: ExpressionPlan {
expressions: vec![
expression(
SemanticType::Bool,
ExpressionOp::Literal {
literal: TypedLiteral::Bool(true),
},
),
expression(
SemanticType::Bool,
ExpressionOp::Literal {
literal: TypedLiteral::Bool(false),
},
),
expression(
SemanticType::U32,
ExpressionOp::U32Construct {
bits: vec![
crate::render_graph::ExprId(0),
crate::render_graph::ExprId(1),
],
},
),
],
},
pipelines: vec![],
requires_camera: false,
};
let wgsl = generate_wgsl(&plan).unwrap();
assert_eq!(
wgsl.lines().find(|line| line.starts_with("let e2=")),
Some("let e2=(select(0u,1u,e0)|select(0u,2u,e1));")
);
}
} }
+1 -113
View File
@@ -1,8 +1,6 @@
use std::{cell::RefCell, rc::Rc, sync::mpsc::Receiver}; use std::{cell::RefCell, rc::Rc, sync::mpsc::Receiver};
use futures::channel::oneshot;
use log::info; use log::info;
use ultraviolet::Vec4;
use wasm_bindgen::{prelude::Closure, JsCast, JsValue}; use wasm_bindgen::{prelude::Closure, JsCast, JsValue};
use wasm_bindgen_futures::spawn_local; use wasm_bindgen_futures::spawn_local;
use web_sys::DedicatedWorkerGlobalScope; use web_sys::DedicatedWorkerGlobalScope;
@@ -1632,7 +1630,7 @@ impl<T: Scene + 'static> Renderer<T> {
sample_count: 1, sample_count: 1,
dimension: wgpu::TextureDimension::D2, dimension: wgpu::TextureDimension::D2,
format: DEPTH_FORMAT, format: DEPTH_FORMAT,
usage: wgpu::TextureUsages::RENDER_ATTACHMENT | wgpu::TextureUsages::COPY_SRC, usage: wgpu::TextureUsages::RENDER_ATTACHMENT,
view_formats: &[], view_formats: &[],
}); });
@@ -2860,98 +2858,6 @@ impl<T: Scene + 'static> Renderer<T> {
let _ = global.post_message(&value); let _ = global.post_message(&value);
} }
pub async fn read_pixel_from_texture(&self, x: u32, y: u32) -> Vec4 {
let width = self.context.depth_texture.width();
let height = self.context.depth_texture.height();
if width == 0 || height == 0 {
log::warn!("Depth texture has zero extent ({} x {})", width, height);
return Vec4::zero();
}
// Validate coordinates
if x >= width || y >= height {
log::warn!(
"Pixel coordinates ({}, {}) out of bounds for texture size {}x{}",
x,
y,
width,
height
);
return Vec4::zero();
}
let pixel_size = std::mem::size_of::<f32>() as u32;
let unpadded_row_bytes = width * pixel_size;
let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT;
let padded_row_bytes = if unpadded_row_bytes % align == 0 {
unpadded_row_bytes
} else {
(unpadded_row_bytes / align + 1) * align
};
let buffer_size = padded_row_bytes as u64 * height as u64;
let buffer = self.context.device.create_buffer(&wgpu::BufferDescriptor {
label: Some("depth pixel read buffer"),
size: buffer_size,
usage: wgpu::BufferUsages::COPY_DST | wgpu::BufferUsages::MAP_READ,
mapped_at_creation: false,
});
// Copy just the single pixel
let mut encoder =
self.context
.device
.create_command_encoder(&wgpu::CommandEncoderDescriptor {
label: Some("copy depth pixel to buffer"),
});
encoder.copy_texture_to_buffer(
wgpu::TexelCopyTextureInfo {
texture: &self.context.depth_texture,
mip_level: 0,
origin: wgpu::Origin3d { x: 0, y: 0, z: 0 },
aspect: wgpu::TextureAspect::DepthOnly,
},
wgpu::TexelCopyBufferInfo {
buffer: &buffer,
layout: wgpu::TexelCopyBufferLayout {
offset: 0,
bytes_per_row: Some(padded_row_bytes),
rows_per_image: Some(height),
},
},
wgpu::Extent3d {
width,
height,
depth_or_array_layers: 1,
},
);
self.context.queue.submit(std::iter::once(encoder.finish()));
// Map the buffer and read the pixel
let slice = buffer.slice(..);
let (tx, rx) = oneshot::channel();
slice.map_async(wgpu::MapMode::Read, move |result| {
tx.send(result).unwrap();
});
// Poll the device to process the mapping
rx.await.unwrap().unwrap();
let depth_value = {
let data = slice.get_mapped_range();
let row_pitch = padded_row_bytes as usize;
let byte_offset = y as usize * row_pitch + x as usize * pixel_size as usize;
let mut depth_bytes = [0u8; 4];
depth_bytes.copy_from_slice(&data[byte_offset..byte_offset + 4]);
f32::from_le_bytes(depth_bytes)
};
buffer.unmap();
Vec4::new(depth_value, 0.0, 0.0, 0.0)
}
pub async fn handle_event(renderer: Rc<RefCell<Self>>, event: WindowEvent) { pub async fn handle_event(renderer: Rc<RefCell<Self>>, event: WindowEvent) {
match event { match event {
WindowEvent::PointerMove(msg) => { WindowEvent::PointerMove(msg) => {
@@ -2961,7 +2867,6 @@ impl<T: Scene + 'static> Renderer<T> {
renderer.borrow_mut().resize(msg); renderer.borrow_mut().resize(msg);
} }
WindowEvent::PointerClick(msg) => { WindowEvent::PointerClick(msg) => {
{
log::info!("click start"); log::info!("click start");
let mut r = renderer.borrow_mut(); let mut r = renderer.borrow_mut();
@@ -2970,27 +2875,10 @@ impl<T: Scene + 'static> Renderer<T> {
r.scene.handle_mouse_click(x, y); r.scene.handle_mouse_click(x, y);
log::info!("clicked"); log::info!("clicked");
} }
// Read pixel from depth texture at click coordinates
// let renderer_clone = renderer.clone();
// let x_coord = msg.offset_x as u32;
// let y_coord = msg.offset_y as u32;
// let pixel_value = renderer_clone
// .borrow()
// .read_pixel_from_texture(x_coord, y_coord)
// .await;
// log::info!(
// "Depth pixel at ({}, {}): {:?}",
// x_coord,
// y_coord,
// pixel_value
// );
}
WindowEvent::PointerWheel(msg) => { WindowEvent::PointerWheel(msg) => {
let mut r = renderer.borrow_mut(); let mut r = renderer.borrow_mut();
r.scene.handle_zoom(msg.delta_y_pixels); r.scene.handle_zoom(msg.delta_y_pixels);
} }
WindowEvent::Keyboard(_) => {}
} }
} }