feat: optimize input system, avoid heap allocations, disable as many events as possible

This commit is contained in:
Ryan Walters
2025-09-02 14:57:01 -05:00
parent 1b0624a174
commit d6d0f47483
2 changed files with 89 additions and 16 deletions

View File

@@ -31,6 +31,7 @@ use bevy_ecs::schedule::common_conditions::resource_changed;
use bevy_ecs::schedule::{Condition, IntoScheduleConfigs, Schedule, SystemSet}; use bevy_ecs::schedule::{Condition, IntoScheduleConfigs, Schedule, SystemSet};
use bevy_ecs::system::ResMut; use bevy_ecs::system::ResMut;
use bevy_ecs::world::World; use bevy_ecs::world::World;
use sdl2::event::EventType;
use sdl2::image::LoadTexture; use sdl2::image::LoadTexture;
use sdl2::render::{BlendMode, Canvas, ScaleMode, TextureCreator}; use sdl2::render::{BlendMode, Canvas, ScaleMode, TextureCreator};
use sdl2::rwops::RWops; use sdl2::rwops::RWops;
@@ -83,8 +84,63 @@ impl Game {
pub fn new( pub fn new(
mut canvas: Canvas<Window>, mut canvas: Canvas<Window>,
texture_creator: TextureCreator<WindowContext>, texture_creator: TextureCreator<WindowContext>,
event_pump: EventPump, mut event_pump: EventPump,
) -> GameResult<Game> { ) -> GameResult<Game> {
// Disable uninteresting events
for event_type in [
EventType::JoyAxisMotion,
EventType::JoyBallMotion,
EventType::JoyHatMotion,
EventType::JoyButtonDown,
EventType::JoyButtonUp,
EventType::JoyDeviceAdded,
EventType::JoyDeviceRemoved,
EventType::ControllerAxisMotion,
EventType::ControllerButtonDown,
EventType::ControllerButtonUp,
EventType::ControllerDeviceAdded,
EventType::ControllerDeviceRemoved,
EventType::ControllerDeviceRemapped,
EventType::ControllerTouchpadDown,
EventType::ControllerTouchpadMotion,
EventType::ControllerTouchpadUp,
EventType::FingerDown,
EventType::FingerUp,
EventType::FingerMotion,
EventType::DollarGesture,
EventType::DollarRecord,
EventType::MultiGesture,
EventType::ClipboardUpdate,
EventType::DropFile,
EventType::DropText,
EventType::DropBegin,
EventType::DropComplete,
EventType::AudioDeviceAdded,
EventType::AudioDeviceRemoved,
EventType::RenderTargetsReset,
EventType::RenderDeviceReset,
EventType::LocaleChanged,
EventType::TextInput,
EventType::TextEditing,
EventType::Display,
EventType::Window,
EventType::MouseWheel,
EventType::MouseMotion,
EventType::MouseButtonDown,
EventType::MouseButtonUp,
EventType::MouseButtonDown,
EventType::AppDidEnterBackground,
EventType::AppWillEnterForeground,
EventType::AppWillEnterBackground,
EventType::AppDidEnterForeground,
EventType::AppLowMemory,
EventType::AppTerminating,
EventType::User,
EventType::Last,
] {
event_pump.disable_event(event_type);
}
let ttf_context = Box::leak(Box::new(sdl2::ttf::init().map_err(|e| GameError::Sdl(e.to_string()))?)); let ttf_context = Box::leak(Box::new(sdl2::ttf::init().map_err(|e| GameError::Sdl(e.to_string()))?));
let mut backbuffer = texture_creator let mut backbuffer = texture_creator
.create_texture_target(None, CANVAS_SIZE.x, CANVAS_SIZE.y) .create_texture_target(None, CANVAS_SIZE.x, CANVAS_SIZE.y)

View File

@@ -7,6 +7,7 @@ use bevy_ecs::{
}; };
use glam::Vec2; use glam::Vec2;
use sdl2::{event::Event, keyboard::Keycode, EventPump}; use sdl2::{event::Event, keyboard::Keycode, EventPump};
use smallvec::{smallvec, SmallVec};
use crate::systems::components::DeltaTime; use crate::systems::components::DeltaTime;
use crate::{ use crate::{
@@ -133,10 +134,22 @@ pub fn input_system(
) { ) {
let mut cursor_seen = false; let mut cursor_seen = false;
// Collect all events for this frame. // Collect all events for this frame.
let frame_events: Vec<Event> = pump.poll_iter().collect(); let frame_events: SmallVec<[Event; 3]> = pump.poll_iter().collect();
// Warn if the smallvec was heap allocated due to exceeding stack capacity
#[cfg(debug_assertions)]
{
if frame_events.len() > frame_events.capacity() {
tracing::warn!(
"More than {} events in a frame, consider adjusting stack capacity: {:?}",
frame_events.capacity(),
frame_events
);
}
}
// Handle non-keyboard events inline and build a simplified keyboard event stream. // Handle non-keyboard events inline and build a simplified keyboard event stream.
let mut simple_key_events = Vec::new(); let mut simple_key_events: SmallVec<[SimpleKeyEvent; 3]> = smallvec![];
for event in &frame_events { for event in &frame_events {
match *event { match *event {
Event::Quit { .. } => { Event::Quit { .. } => {
@@ -149,21 +162,25 @@ pub fn input_system(
}; };
cursor_seen = true; cursor_seen = true;
} }
Event::KeyDown { Event::KeyDown { keycode, repeat, .. } => {
keycode: Some(key), if let Some(key) = keycode {
repeat: false, if repeat {
.. continue;
} => { }
simple_key_events.push(SimpleKeyEvent::KeyDown(key)); simple_key_events.push(SimpleKeyEvent::KeyDown(key));
}
} }
Event::KeyUp { Event::KeyUp { keycode, repeat, .. } => {
keycode: Some(key), if let Some(key) = keycode {
repeat: false, if repeat {
.. continue;
} => { }
simple_key_events.push(SimpleKeyEvent::KeyUp(key)); simple_key_events.push(SimpleKeyEvent::KeyUp(key));
}
}
_ => {
tracing::warn!("Unhandled event, consider disabling: {:?}", event);
} }
_ => {}
} }
} }