not-fl3 / macroquad

Cross-platform game engine in Rust.
Apache License 2.0
3.04k stars 297 forks source link

DrawCanvas::image() exceeds max drawcalls too early #724

Open vjodar opened 1 month ago

vjodar commented 1 month ago

I've come across an issue where 800-900 calls to DrawCanvas::image() at a time would produce the following warning and ignore any remaining texture draws.

C:\Program Files\Rust\testies>cargo run --release
    Finished release [optimized] target(s) in 0.23s
     Running `target\release\testies.exe`
geometry() exceeded max drawcall size, clamping

Obviously the limit shouldn't be this low, and indeed draw_texture() has no such issue, nor does DrawCanvas::rect().

Digging through src/ui/render/mesh_resterizer::DrawList::draw_rectangle(), 900 calls to DrawCanvas::image() results in 3600 vertices and 5400 indices, which checks out (4 vertices and 6 indices per rectangle), however 900 calls to DrawCanvas::rect() results in 940 vertices and 1410 indices for solid rectangles, so it seems like there's some optimization going on here that doesn't happen for DrawCanvas::image().

I haven't been able to track down the issue, though I have discovered a workaround being a call to DrawCanvas::rect() before reaching the limit will reset the vertices and indices manually. I've included this in the code below that can be used to reproduce the bug.

use macroquad::prelude::*;
use macroquad::ui::root_ui;

#[macroquad::main("")]
async fn main() {
    let texture = Texture2D::empty();
    let max = 800;      

    loop {      
        if is_key_pressed(KeyCode::Escape) { return }

        let mut count = 0;

        for _ in 0..2000 {
            let x = rand::gen_range(0., 800.);
            let y = rand::gen_range(0., 600.);
            root_ui().canvas().image(Rect::new(x, y, 10., 10.), &texture);

            // Comment out below for bug --------------------------------------
            count += 1;
            if count > max {
                count = 0;
                root_ui().canvas().rect(Rect::new(0., 0., 0., 0.), None, None);
            }
            // ----------------------------------------------------------------
        }

        next_frame().await;
    }
}