emoon / rust_minifb

Cross platfrom window and framebuffer crate for Rust
MIT License
1.04k stars 99 forks source link

High Memory Usage and Segfault When Using RefCell with minifb #370

Open FalkAurel opened 3 weeks ago

FalkAurel commented 3 weeks ago

Hey I've been trying to build a simple gui application using minifb but couldn't help but notice, that it a draws ungodly amounts of ram and segfaults the moment I use a RefCell to manage the window with respect to ownership. This very primitive setup draws roughly 70-90 MB. I'm running this code on MacBook M2 Air with rustc 1.80.0 (051478957 2024-07-21) and minifb version minifb = "0.27.0".

use image::window::initialize;
use minifb::Window;

fn main() {
    let mut window: Window = initialize("Test", 1080, 720).unwrap();

    let buffer: Vec<u32> = vec![0xFF000000; 1080 * 720];

    while window.is_open() {
        window.update_with_buffer(&buffer, 1080, 720);
    }
}

The following setup will cause a bus error. I assume it's likely due to some memory misalignment on minifb's part when having the window wrapped in a RefCell.

use image::{canvas::Canvas, window::initialize};
use minifb::Window;

use std::{borrow::BorrowMut, cell::RefCell};

fn main() {
    let window: Window = initialize("Test", 1080, 720).unwrap();

    let window: RefCell<Window> = RefCell::new(window);
    let mut canvas: Canvas = Canvas::new(&window);

    while window.borrow().is_open() {
        if let Err(err) = canvas.borrow_mut().draw() {
            eprintln!("[WINDOW ERROR]: {err}");
            std::process::exit(-2);
        }
    }
}

This is the code for my Canvas

use minifb::Window;
use std::cell::RefCell;
use crate::{backend::Render, error::Error};

const DEFAULT_BACKGROUND_COLOUR: u32 = 0xFF000000;

pub struct Canvas<'a> {
    window: &'a RefCell<Window>,
    buffer: Vec<u32>
}

impl <'a> Canvas<'a> {
    pub fn new(window: &'a RefCell<Window>) -> Self {
        let (width, height) = window.borrow().get_size();
        Self { window, buffer: vec![DEFAULT_BACKGROUND_COLOUR; width * height] }
    }

    // Copies drawables into buffer
    pub fn blit(&mut self, element: &dyn Render) {
        element.copy_into_buffer(&mut self.buffer)
    }

    pub fn draw(&mut self) -> Result<(), Error> {
        let (width, height) = self.window.borrow().get_size();
        self.window.borrow_mut().update_with_buffer(&self.buffer, width, height)
            .map_err(|err| Error::WindowError(err))
    }
}

Here's a quick screenshot of my, in my opinion very high ram consumption. Screenshot 2024-10-27 at 12 48 01

emoon commented 3 weeks ago

Hey,

Thanks for the report. I will try to have a look at it when I can.

FalkAurel commented 3 weeks ago

Hey,

Thanks for the report. I will try to have a look at it when I can.

👍