Skip to content

Commit dcdca05

Browse files
committed
fix(doom): various optimizations
optimize screen rendering by removing bounds check and using offsets to give llvm better optimization options
1 parent f878541 commit dcdca05

File tree

9 files changed

+46
-43
lines changed

9 files changed

+46
-43
lines changed

beskar-lib/src/lib.rs

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,9 +84,10 @@ pub fn __init() {
8484
#[inline]
8585
/// In debug builds, triggers a breakpoint interrupt (`int3`).
8686
pub fn debug_break() {
87-
#[cfg(debug_assertions)]
88-
unsafe {
89-
core::arch::asm!("int3", options(nomem, nostack, preserves_flags));
87+
if cfg!(debug_assertions) {
88+
unsafe {
89+
core::arch::asm!("int3", options(nomem, nostack, preserves_flags));
90+
}
9091
}
9192
}
9293

@@ -95,8 +96,9 @@ pub fn debug_break() {
9596
///
9697
/// The provided value `x` is placed in the `RAX` register before triggering the interrupt.
9798
pub fn debug_break_value(x: u64) {
98-
#[cfg(debug_assertions)]
99-
unsafe {
100-
core::arch::asm!("int3", in("rax") x, options(nomem, nostack, preserves_flags));
99+
if cfg!(debug_assertions) {
100+
unsafe {
101+
core::arch::asm!("int3", in("rax") x, options(nomem, nostack, preserves_flags));
102+
}
101103
}
102104
}

kernel/src/process/binary/elf/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -74,8 +74,6 @@
7474
#![warn(clippy::pedantic, clippy::nursery)]
7575
#![no_std]
7676

77-
extern crate alloc;
78-
7977
mod error;
8078
mod loader;
8179
pub mod mapper;

kernel/src/process/binary/elf/src/loader.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ impl ElfLoader {
7373
Ok(LoadedBinary {
7474
entry_point,
7575
tls_template,
76+
image_size: addr_range.size(),
7677
})
7778
}
7879

kernel/src/process/binary/elf/src/segments.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,4 +20,6 @@ pub struct LoadedBinary {
2020
pub entry_point: extern "C" fn(),
2121
/// TLS template (if present)
2222
pub tls_template: Option<TlsTemplate>,
23+
/// Image size in memory
24+
pub image_size: u64,
2325
}

userspace/doom/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
2929
.flag("-w")
3030
// compile without simd
3131
.flag("-mgeneral-regs-only")
32+
.flag("-flto")
3233
.compile("puredoom");
3334

3435
Ok(())

userspace/doom/src/game.rs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use core::{
2-
ffi::{c_char, c_void},
2+
ffi::{CStr, c_char, c_void},
33
sync::atomic::{AtomicUsize, Ordering},
44
};
55

@@ -33,15 +33,14 @@ pub fn init() {
3333
unsafe { doom_set_getenv(getenv) };
3434
}
3535

36-
#[cfg(debug_assertions)]
3736
extern "C" fn print(s: *const c_char) {
38-
let s = unsafe { core::ffi::CStr::from_ptr(s) };
39-
if let Ok(s) = s.to_str() {
40-
beskar_lib::println!("DOOM: {}", s);
37+
if !cfg!(debug_assertions) {
38+
let s = unsafe { CStr::from_ptr(s) };
39+
if let Ok(s) = s.to_str() {
40+
beskar_lib::println!("DOOM: {}", s);
41+
}
4142
}
4243
}
43-
#[cfg(not(debug_assertions))]
44-
extern "C" fn print(_s: *const c_char) {}
4544

4645
extern "C" fn malloc(size: i32) -> *mut c_void {
4746
// `alloc` states the layout size must be non-zero.
@@ -57,8 +56,7 @@ extern "C" fn malloc(size: i32) -> *mut c_void {
5756

5857
assert!(
5958
!ptr.is_null(),
60-
"malloc failed: out of memory (requested {} bytes)",
61-
size
59+
"malloc failed: out of memory (requested {size} bytes)",
6260
);
6361

6462
ptr.cast()

userspace/doom/src/input.rs

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use beskar_lib::io::keyboard::{KeyCode, KeyEvent, KeyState, KeyboardReader};
1+
use beskar_lib::io::keyboard::{KeyCode, KeyState, KeyboardReader};
22
use hyperdrive::{locks::ticket::TicketLock, once::Once};
33

44
#[link(name = "puredoom", kind = "static")]
@@ -164,23 +164,18 @@ impl From<KeyCode> for DoomKeyT {
164164
}
165165
}
166166

167-
#[must_use]
168-
#[inline]
167+
/// Polls the keyboard and redistributes events to Doom.
168+
///
169169
/// # Panics
170170
///
171-
/// This function panics if opening the keyboard file fails (only once).
172-
fn poll_keyboard() -> Option<KeyEvent> {
171+
/// This function will panic if the keyboard reader cannot be initialized.
172+
pub fn poll_inputs() {
173173
static KEYBOARD_READER: Once<TicketLock<KeyboardReader>> = Once::uninit();
174174

175175
KEYBOARD_READER.call_once(|| TicketLock::new(KeyboardReader::new().unwrap()));
176176
let mut reader = KEYBOARD_READER.get().unwrap().lock();
177177

178-
reader.next_event().unwrap_or(None)
179-
}
180-
181-
/// Polls the keyboard and redistributes events to Doom.
182-
pub fn poll_inputs() {
183-
while let Some(event) = poll_keyboard() {
178+
while let Ok(Some(event)) = reader.next_event() {
184179
let doom_key = DoomKeyT::from(event.key());
185180
match event.pressed() {
186181
KeyState::Pressed => unsafe { doom_key_down(doom_key) },

userspace/doom/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ fn main() {
2222
unsafe { doom_init(1, argv.as_ptr(), 0b111) };
2323

2424
loop {
25+
doom::input::poll_inputs();
2526
unsafe { doom_update() };
2627
doom::screen::draw();
27-
doom::input::poll_inputs();
2828
}
2929
}

userspace/doom/src/screen.rs

Lines changed: 20 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ pub fn init() {
2424
SCREEN_INFO.call_once(|| SCREEN.with_locked(|screen| *screen.info()));
2525
}
2626

27+
#[must_use]
28+
#[inline]
2729
/// Returns the screen info.
2830
///
2931
/// # Panics
@@ -33,29 +35,33 @@ fn screen_info() -> &'static Info {
3335
SCREEN_INFO.get().unwrap()
3436
}
3537

38+
#[inline]
3639
fn with_screen<R, F: FnOnce(&mut FrameBuffer) -> R>(f: F) -> R {
3740
SCREEN.with_locked(f)
3841
}
3942

4043
/// Draw the Doom framebuffer to the screen
4144
pub fn draw() {
42-
let fb_start = unsafe { doom_get_framebuffer(CHANNELS.try_into().unwrap()) };
43-
let fb_raw = core::ptr::slice_from_raw_parts(fb_start, SCREENWIDTH * SCREENHEIGHT * CHANNELS);
45+
let fb_start = unsafe { doom_get_framebuffer(CHANNELS as i32) };
4446

45-
let Some(fb) = (unsafe { fb_raw.as_ref() }) else {
46-
beskar_lib::println!("Warning: Doom framebuffer is not initialized");
47-
return;
48-
};
47+
let info = screen_info();
48+
let stride_bytes = usize::from(info.stride()) * usize::from(info.bytes_per_pixel());
49+
let row_size = SCREENWIDTH * CHANNELS;
4950

50-
let stride = usize::from(screen_info().stride());
51-
let bpp = usize::from(screen_info().bytes_per_pixel());
52-
let stride_bytes = stride * bpp;
5351
with_screen(|screen| {
54-
let mut buffer_mut = screen.buffer_mut();
55-
for row in fb.chunks_exact(SCREENWIDTH * CHANNELS) {
56-
buffer_mut[..SCREENWIDTH * CHANNELS].copy_from_slice(row);
57-
buffer_mut = &mut buffer_mut[stride_bytes..];
52+
let dst = screen.buffer_mut().as_mut_ptr();
53+
let src = fb_start;
54+
55+
for y in 0..SCREENHEIGHT {
56+
unsafe {
57+
core::ptr::copy_nonoverlapping(
58+
src.add(y * row_size),
59+
dst.add(y * stride_bytes),
60+
row_size,
61+
);
62+
}
5863
}
59-
let _ = screen.flush_rows(0..u16::try_from(SCREENHEIGHT).unwrap());
64+
65+
let _ = screen.flush_rows(0..SCREENHEIGHT as u16);
6066
});
6167
}

0 commit comments

Comments
 (0)